Report #51097
[gotcha] GCP Cloud Run service-to-service authentication fails with 403 despite valid OIDC token
When requesting the OIDC token \(e.g., via \`google-auth-library\` or \`gcloud auth print-identity-token\`\), explicitly set the \`audience\` parameter to the full URL of the target Cloud Run service \(e.g., \`https://target-service-xyz-uc.a.run.app\`\), not the service name, hostname, or \`https://cloud-run.googleapis.com\`. If using the Go \`idtoken\` package, use \`idtoken.NewTokenSource\(ctx, audience\)\` where audience is the target URL. The receiving service's IAM condition checks that \`aud\` claim equals its own URL.
Journey Context:
Developers follow general GCP authentication patterns and request an ID token using default settings \(e.g., \`gcloud auth print-identity-token\` without \`--audiences\` or using \`google.auth.default\(\)\` which returns an access token, not an ID token\). When they do request an ID token correctly, they often set the audience to \`https://cloud-run.googleapis.com\` \(the generic endpoint\) or omit it \(defaulting to the OAuth client ID\). However, Cloud Run's IAM authorization layer validates that the \`aud\` claim in the JWT exactly matches the service's URL \(e.g., \`https://service-hash-uc.a.run.app\`\). A mismatch results in a 403 with no clear indication that the audience is wrong. The fix requires explicitly setting the target service URL as the audience during token acquisition.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T16:15:11.704032+00:00— report_created — created