Overview
Protect routes with JWT authentication using @fastify/jwt. Supports role-based access control and token refresh.
Features
- JWT verification via @fastify/jwt
- Role-based access control
- Token generation helpers
- Refresh token support
- Customizable error responses
Installation
npx hanma add fastify-jwt --framework fastify
Dependencies
fastify, @fastify/jwt
Code
import { FastifyInstance, FastifyRequest, FastifyReply } from "fastify";
import jwt from "@fastify/jwt";
interface JwtPayload {
id: string;
email: string;
roles: string[];
}
declare module "@fastify/jwt" {
interface FastifyJWT {
payload: JwtPayload;
user: JwtPayload;
}
}
export async function registerJwtAuth(app: FastifyInstance): Promise<void> {
await app.register(jwt, {
secret: process.env.JWT_SECRET ?? "your-secret-key-change-in-production",
sign: {
expiresIn: process.env.JWT_EXPIRES_IN ?? "7d",
},
verify: {
maxAge: process.env.JWT_EXPIRES_IN ?? "7d",
},
});
// Decorate with authenticate method
app.decorate("authenticate", async (request: FastifyRequest, reply: FastifyReply) => {
try {
await request.jwtVerify();
} catch (err) {
reply.status(401).send({
error: "Unauthorized",
message: "Invalid or missing authentication token",
});
}
});
}
// Middleware to verify JWT
export async function authenticate(
request: FastifyRequest,
reply: FastifyReply
): Promise<void> {
try {
await request.jwtVerify();
} catch (err) {
reply.status(401).send({
error: "Unauthorized",
message: "Invalid or missing authentication token",
});
}
}
// Middleware to check roles
export function authorize(allowedRoles: string[]) {
return async (request: FastifyRequest, reply: FastifyReply): Promise<void> => {
try {
await request.jwtVerify();
const user = request.user;
const hasRole = user.roles.some((role) => allowedRoles.includes(role));
if (!hasRole) {
reply.status(403).send({
error: "Forbidden",
message: "Insufficient permissions",
required: allowedRoles,
});
}
} catch (err) {
reply.status(401).send({
error: "Unauthorized",
message: "Invalid or missing authentication token",
});
}
};
}
// Generate tokens
export function generateTokens(app: FastifyInstance, payload: JwtPayload) {
const accessToken = app.jwt.sign(payload);
const refreshToken = app.jwt.sign(payload, { expiresIn: "30d" });
return { accessToken, refreshToken };
}
// Optional: Refresh token handler
export async function refreshTokenHandler(
request: FastifyRequest,
reply: FastifyReply
): Promise<void> {
try {
const decoded = await request.jwtVerify();
const newToken = request.server.jwt.sign({
id: decoded.id,
email: decoded.email,
roles: decoded.roles,
});
reply.send({ accessToken: newToken });
} catch (err) {
reply.status(401).send({
error: "Unauthorized",
message: "Invalid refresh token",
});
}
}
// Usage:
// await registerJwtAuth(app);
// app.get("/protected", { preHandler: [authenticate] }, handler);
// app.get("/admin", { preHandler: [authorize(["admin"])] }, handler);
Usage
import { registerJwtAuth, authenticate, authorize } from './middleware/jwt-auth';
await registerJwtAuth(app);
app.get('/admin', { preHandler: [authorize(['admin'])] }, handler);
Dependencies
fastify@fastify/jwt
Frequently Asked Questions
How do I install JWT Authentication?
Run the following command:
npx hanma add fastify-jwt --framework fastifyWhat dependencies are required?
This snippet requires: fastify, @fastify/jwt. Make sure to install them before using the snippet.
How do I use this snippet?
Copy the code and paste it into your project. The snippet will be saved to
src/middleware/jwt-auth.ts.Can I customize this snippet?
Yes! All snippets are copy-paste code that you own. Feel free to modify them to fit your needs.
Does this work with other frameworks?
This snippet is designed for the specific framework. Check the other framework pages for equivalent implementations.