import { Injectable, CanActivate, ExecutionContext, UnauthorizedException, } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { ConfigService } from '@nestjs/config'; import { SKIP_API_TOKEN_KEY } from '../decorators/skip-api-token.decorator'; import { IS_PUBLIC_KEY } from '../decorators/public.decorator'; @Injectable() export class ApiTokenGuard implements CanActivate { constructor( private reflector: Reflector, private configService: ConfigService, ) {} canActivate(context: ExecutionContext): boolean { // Check if API token validation is enabled const isEnabled = this.configService.get('API_TOKEN_ENABLED') === 'true'; if (!isEnabled) { return true; } // Check if route is marked to skip API token validation const skipApiToken = this.reflector.getAllAndOverride( SKIP_API_TOKEN_KEY, [context.getHandler(), context.getClass()], ); if (skipApiToken) { return true; } // Check if route is marked as public (optional - you can remove this if you want public routes to still require API token) const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [ context.getHandler(), context.getClass(), ]); if (isPublic) { return true; } const request = context.switchToHttp().getRequest(); const token = request.headers['x-api-token']; if (!token) { throw new UnauthorizedException( 'API token is required. Please provide x-api-token header.', ); } const validToken = this.configService.get('API_SECRET_TOKEN'); if (!validToken) { throw new UnauthorizedException('API token is not configured on server.'); } if (token !== validToken) { throw new UnauthorizedException('Invalid API token.'); } return true; } }