38 lines
1.4 KiB
TypeScript
38 lines
1.4 KiB
TypeScript
import { Injectable, NestMiddleware, UnauthorizedException } from '@nestjs/common';
|
|
import { Request, Response, NextFunction } from 'express';
|
|
import * as jwt from 'jsonwebtoken';
|
|
import { validate as isValidUUID } from 'uuid';
|
|
|
|
@Injectable()
|
|
export class JwtMiddleware implements NestMiddleware {
|
|
use(req: Request, res: Response, next: NextFunction) {
|
|
const authHeader = req.headers.authorization;
|
|
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
|
throw new UnauthorizedException('Missing or invalid Authorization header');
|
|
}
|
|
|
|
const token = authHeader.split(' ')[1];
|
|
try {
|
|
const decoded = jwt.decode(token) as any;
|
|
if (!decoded || !decoded.sub) {
|
|
throw new UnauthorizedException('Invalid token: missing sub');
|
|
}
|
|
if (!isValidUUID(decoded.sub)) {
|
|
throw new UnauthorizedException('Invalid token: sub is not a valid UUIDv4');
|
|
}
|
|
const { sub, realm_access, resource_access } = decoded;
|
|
const roles = [ // extract the role you wanna use in guards
|
|
...(realm_access?.roles || []),
|
|
// ...(resource_access?.account?.roles || []),
|
|
];
|
|
req['user'] = { sub, roles };
|
|
next();
|
|
} catch (error) {
|
|
throw new UnauthorizedException('Invalid token');
|
|
}
|
|
}
|
|
}
|
|
|
|
export interface AuthRequest extends Request {
|
|
user: { sub: string; roles: string[] };
|
|
} |