48 lines
1.3 KiB
TypeScript
48 lines
1.3 KiB
TypeScript
import fp from 'fastify-plugin';
|
|
import jwt from '@fastify/jwt';
|
|
import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
|
|
import type { AccessTokenPayload } from '../lib/jwt.js';
|
|
|
|
declare module 'fastify' {
|
|
interface FastifyInstance {
|
|
authenticate: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
}
|
|
}
|
|
|
|
declare module '@fastify/jwt' {
|
|
interface FastifyJWT {
|
|
payload: AccessTokenPayload;
|
|
user: AccessTokenPayload;
|
|
}
|
|
}
|
|
|
|
export default fp(async (app: FastifyInstance) => {
|
|
const jwtSecret = process.env.JWT_SECRET;
|
|
const jwtRefreshSecret = process.env.JWT_REFRESH_SECRET;
|
|
|
|
if (!jwtSecret || !jwtRefreshSecret) {
|
|
throw new Error('JWT_SECRET and JWT_REFRESH_SECRET environment variables are required');
|
|
}
|
|
|
|
// Access token JWT
|
|
await app.register(jwt, {
|
|
secret: jwtSecret,
|
|
});
|
|
|
|
// Refresh token JWT (separate namespace)
|
|
await app.register(jwt, {
|
|
secret: jwtRefreshSecret,
|
|
namespace: 'refresh',
|
|
decoratorName: 'jwtRefresh',
|
|
});
|
|
|
|
// Auth decorator
|
|
app.decorate('authenticate', async (request: FastifyRequest, reply: FastifyReply) => {
|
|
try {
|
|
await request.jwtVerify();
|
|
} catch {
|
|
reply.code(401).send({ error: 'Unauthorized', message: 'Invalid or expired token' });
|
|
}
|
|
});
|
|
});
|