From 1c926921edec4045ddc2698866eb994c8ad7477a Mon Sep 17 00:00:00 2001 From: Adam Weidman Date: Thu, 12 Feb 2026 12:19:35 -0500 Subject: [PATCH] fix: delegate auth to Cloud Run IAM when K_SERVICE is set Cloud Run strips the Authorization header after using it for IAM validation, so our JWT middleware can never see the token. When running on Cloud Run (detected via K_SERVICE env var), skip app-level JWT verification since Cloud Run IAM already ensures only authorized service accounts (chat@system.gserviceaccount.com) can reach the container. --- packages/a2a-server/src/chat-bridge/routes.ts | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/a2a-server/src/chat-bridge/routes.ts b/packages/a2a-server/src/chat-bridge/routes.ts index ea71f62a19..e589a3f538 100644 --- a/packages/a2a-server/src/chat-bridge/routes.ts +++ b/packages/a2a-server/src/chat-bridge/routes.ts @@ -21,13 +21,31 @@ const CHAT_ISSUER = 'chat@system.gserviceaccount.com'; /** * Creates middleware that verifies Google Chat JWT tokens. - * When projectNumber is set, requests must include a valid Bearer token - * signed by Google Chat with the correct audience. - * When not set, verification is skipped (for local testing). + * + * On Cloud Run (detected via K_SERVICE env var), authentication is handled by + * Cloud Run's IAM layer — only principals with roles/run.invoker can reach the + * container. Cloud Run strips the Authorization header after validation, so our + * middleware cannot re-verify the token. We trust Cloud Run's IAM instead. + * + * When NOT on Cloud Run and projectNumber is set, requests must include a valid + * Bearer token signed by Google Chat with the correct audience. + * + * When neither condition applies, verification is skipped (local testing). */ function createAuthMiddleware( projectNumber: string | undefined, ): (req: Request, res: Response, next: NextFunction) => void { + // On Cloud Run, IAM handles auth — the Authorization header is stripped + // before reaching the container, so we cannot verify it ourselves. + if (process.env['K_SERVICE']) { + logger.info( + '[ChatBridge] Running on Cloud Run — auth delegated to Cloud Run IAM.', + ); + return (_req: Request, _res: Response, next: NextFunction) => { + next(); + }; + } + if (!projectNumber) { logger.warn( '[ChatBridge] CHAT_PROJECT_NUMBER not set — JWT verification disabled. ' +