Skip to main content

Authentication

info

Use AdditionalRequest to share data between hooks and controller.

Examples

cd server
npm install @fastify/jwt

Register the plugin

$/service/app.ts
import Fastify, { FastifyServerFactory } from 'fastify';
import fastifyJwt from '@fastify/jwt';
import { API_JWT_SECRET, API_BASE_PATH } from '$/service/envValues';
import server from './$server';

export const init = (serverFactory?: FastifyServerFactory) => {
const app = Fastify({ serverFactory });
app.register(fastifyJwt, { secret: API_JWT_SECRET });
server(app, { basePath: API_BASE_PATH });
return app;
};

Issue tokens

$/api/token/controller.ts
import { defineController } from './$relay';
import { validateUser } from '$/service/user';

export default defineController((fastify) => ({
post: ({ body }) =>
validateUser(body.id, body.pass)
? { status: 201, body: { token: fastify.jwt.sign({ id: body.id }) } }
: { status: 401 },
}));

Verify tokens

Although @fastify/jwt extends FastifyRequest, it is not reflected to the controller, so you need to prepare it yourself in order to reference it in the controller.

Relaying of type extended by plugins

$/api/user/hooks.ts
import { defineHooks } from './$relay';

export type AdditionalRequest = {
user: {
id: string;
};
};

export default defineHooks(() => ({
onRequest: (request, reply) => request.jwtVerify().catch((err) => reply.send(err)),
}));
$/api/user/controller.ts
import { defineController } from './$relay';
import { getUserNameById } from '$/service/user';

export default defineController(() => ({
get: async ({ user }) => ({ status: 200, body: await getUserNameById(user.id) }),
// ^^^^ extended by AdditionalRequest
}));