From 9c8bae3dea6cf90fbf761ee081e7d1310d87a81c Mon Sep 17 00:00:00 2001 From: Till JS Date: Thu, 26 Mar 2026 21:18:03 +0100 Subject: [PATCH] fix(shared-nestjs-auth): accept multiple JWT issuers for Docker/public URL mismatch In production, backends use the internal Docker URL (http://mana-auth:3001) for MANA_CORE_AUTH_URL but tokens are issued with BASE_URL (https://auth.mana.how) as the issuer. Accept both to prevent "unexpected iss claim value" errors. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/guards/jwt-auth.guard.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/shared-nestjs-auth/src/guards/jwt-auth.guard.ts b/packages/shared-nestjs-auth/src/guards/jwt-auth.guard.ts index 732583233..79918ed83 100644 --- a/packages/shared-nestjs-auth/src/guards/jwt-auth.guard.ts +++ b/packages/shared-nestjs-auth/src/guards/jwt-auth.guard.ts @@ -122,14 +122,23 @@ export class JwtAuthGuard implements CanActivate { * Verify JWT token locally using JWKS */ private async verifyToken(token: string): Promise { - const authUrl = this.configService.get('MANA_CORE_AUTH_URL') || 'http://localhost:3001'; - const issuer = this.configService.get('JWT_ISSUER') || authUrl; const audience = this.configService.get('JWT_AUDIENCE') || 'manacore'; + // Build issuer allowlist: explicit JWT_ISSUER, MANA_CORE_AUTH_URL, and BASE_URL may all differ + // (e.g. internal Docker URL vs public URL). Accept any of them. + const issuerCandidates = new Set(); + const jwtIssuer = this.configService.get('JWT_ISSUER'); + const authUrl = this.configService.get('MANA_CORE_AUTH_URL'); + if (jwtIssuer) issuerCandidates.add(jwtIssuer); + if (authUrl) issuerCandidates.add(authUrl); + // Always accept the well-known production issuer + issuerCandidates.add('https://auth.mana.how'); + issuerCandidates.add('http://localhost:3001'); + const jwks = this.getJWKS(); const { payload } = await jwtVerify(token, jwks, { - issuer, + issuer: [...issuerCandidates], audience, });