76 lines
2.2 KiB
TypeScript
76 lines
2.2 KiB
TypeScript
import {
|
|
Injectable,
|
|
CanActivate,
|
|
ExecutionContext,
|
|
UnauthorizedException,
|
|
} from '@nestjs/common';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import { Reflector } from '@nestjs/core';
|
|
import * as jwt from 'jsonwebtoken';
|
|
import { IS_PUBLIC_KEY } from './public.decorator';
|
|
|
|
@Injectable()
|
|
export class JwtAuthGuard implements CanActivate {
|
|
constructor(
|
|
private readonly configService: ConfigService,
|
|
private readonly reflector: Reflector,
|
|
) { }
|
|
|
|
canActivate(context: ExecutionContext): boolean {
|
|
// 1. Check if route is public
|
|
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
|
|
context.getHandler(),
|
|
context.getClass(),
|
|
]);
|
|
|
|
if (isPublic) {
|
|
return true;
|
|
}
|
|
|
|
const request = context.switchToHttp().getRequest();
|
|
const token = this.extractToken(request);
|
|
|
|
if (!token) {
|
|
throw new UnauthorizedException('Missing authentication token');
|
|
}
|
|
|
|
try {
|
|
const secret = this.configService.get<string>('JWT_SECRET');
|
|
if (!secret) {
|
|
throw new UnauthorizedException('JWT secret not configured');
|
|
}
|
|
|
|
const payload = jwt.verify(token, secret) as any;
|
|
|
|
// 2. Role Check (from HEAD)
|
|
// Only allow admin users to access backoffice
|
|
if (payload.role !== 'admin' && payload.role !== 'superadmin') {
|
|
throw new UnauthorizedException('Admin access required');
|
|
}
|
|
|
|
request.user = payload;
|
|
return true;
|
|
} catch {
|
|
throw new UnauthorizedException('Invalid or expired token');
|
|
}
|
|
}
|
|
|
|
private extractToken(request: any): string | null {
|
|
// 1. Try Authorization header first
|
|
const authHeader = request.headers?.authorization;
|
|
if (authHeader && authHeader.startsWith('Bearer ')) {
|
|
return authHeader.slice(7);
|
|
}
|
|
|
|
// 2. Fallback to cookies (support both names)
|
|
const cookies = request.cookies;
|
|
if (cookies?.jwt) {
|
|
return cookies.jwt;
|
|
}
|
|
if (cookies?.auth_token) {
|
|
return cookies.auth_token;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|