import { CanActivate, ExecutionContext, Injectable, UnauthorizedException, } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { JwtService } from "@nestjs/jwt"; import { Request } from "express"; /** * Verifies the bearer tokens WE minted for CBE at /cbe/oauth/token (plan D7). Its secret * (CBE_BILL_JWT_SECRET) is disjoint from ServiceAuthGuard's shared token: a CBE token must * never authenticate a call to /payments/*, and vice versa. */ @Injectable() export class CbeAuthGuard implements CanActivate { constructor( private readonly jwtService: JwtService, private readonly config: ConfigService, ) {} async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest(); const auth = request.headers.authorization; if (!auth?.startsWith("Bearer ")) { throw new UnauthorizedException("Missing bearer token"); } try { await this.jwtService.verifyAsync(auth.substring(7), { secret: this.config.get("cbeBill.jwtSecret"), }); return true; } catch { throw new UnauthorizedException("Invalid or expired token"); } } }