Skip to main content
Version: v4

Authenticating Users in the API

Now that the login is configured, you can add two new routes to create and delete stories. Their access will be limited to authenticated users.

API endpointMethodDescription
/api/storiesPOSTCreates a new story.
/api/stories/:storyIdDELETEDeletes a story.

Open the stories.controller.ts file and add two new methods to the controller.

import { Context, Delete, Get, HttpResponseCreated, HttpResponseNoContent, HttpResponseNotFound, HttpResponseOK, Post, UserRequired, ValidateBody, ValidatePathParam, ValidateQueryParam } from '@foal/core';
import { Story, User } from '../../entities';

export class StoriesController {

// readStories...

type: 'object',
properties: {
title: { type: 'string', maxLength: 255 },
link: { type: 'string', maxLength: 255 },
required: [ 'title', 'link' ],
additionalProperties: false,
async createStory(ctx: Context<User>) {
const story = new Story();
story.title = ctx.request.body.title; =;
// Set the current user as the author of the story. = ctx.user;

return new HttpResponseCreated();

@ValidatePathParam('storyId', { type: 'number' })
async deleteStory(ctx: Context<User>, { storyId }: { storyId: number }) {
// Only retrieve stories whose author is the current user.
const story = await Story.findOneBy({ id: storyId, author: { id: } });

if (!story) {
return new HttpResponseNotFound();

await story.remove();

return new HttpResponseNoContent();


When sending a request to these endpoints, the @UserRequired hook will return a 401 error if ctx.user is null (i.e. if the user has not logged in first). But if it is, the controller method will be executed.

Go to http://localhost:3001/swagger and check that the controller is working as expected. You can, for example, first try to create a story without being connected and then log in and try again.