{"record":{"id":"813c84979ed232f7","repo":"ory/kratos","slug":"token-audience-didn-t-match-allowed-audiences-v","errorCode":null,"errorMessage":"token audience didn't match allowed audiences: %+v %w","messagePattern":"token audience didn't match allowed audiences: %\\+v %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"selfservice/strategy/oidc/token_verifier.go","lineNumber":40,"sourceCode":"\t\tverifier := oidc.NewVerifier(issuerURL, keySet, &oidc.Config{\n\t\t\tClientID: aud,\n\t\t})\n\t\tt0 := time.Now()\n\t\ttoken, err = verifier.Verify(ctx, rawIDToken)\n\t\treqlog.AccumulateExternalLatency(ctx, time.Since(t0))\n\t\tif err != nil && strings.Contains(err.Error(), \"oidc: expected audience\") {\n\t\t\t// The audience is not the one we expect, try the next one\n\t\t\tcontinue\n\t\t} else if err != nil {\n\t\t\t// Something else went wrong\n\t\t\treturn nil, err\n\t\t}\n\t\t// The token was verified successfully\n\t\tbreak\n\t}\n\tif err != nil {\n\t\t// None of the allowed audiences matched the audience in the token\n\t\treturn nil, fmt.Errorf(\"token audience didn't match allowed audiences: %+v %w\", tokenAudiences, err)\n\t}\n\tclaims := &Claims{}\n\tvar rawClaims map[string]any\n\n\tif token == nil {\n\t\treturn nil, fmt.Errorf(\"token is nil\")\n\t}\n\n\tif err := token.Claims(claims); err != nil {\n\t\treturn nil, err\n\t}\n\tif err = token.Claims(&rawClaims); err != nil {\n\t\treturn nil, err\n\t}\n\tclaims.RawClaims = rawClaims\n\n\treturn claims, nil\n}","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/selfservice/strategy/oidc/token_verifier.go#L22-L58","documentation":"After the verifyToken audience loop completes without success, the last verification error is wrapped as \"token audience didn't match allowed audiences: %+v %w\", listing all allowed audiences (tokenAudiences) and the underlying verification error. It is the user-facing aggregate of a failed ID-token verification across every configured audience.","triggerScenarios":"Every oidc.Verifier.Verify call in verifyToken failed — either because aud did not match (see the audience error) or because the underlying verification failed (expired token, bad signature, wrong issuer). Raised from Verify whenever the loop's final err is non-nil.","commonSituations":"Expired or not-yet-valid ID tokens; signature verification failures from a stale/misconfigured JWKS or wrong issuer URL; audience mismatch as in error [35]; switching providers without updating issuer_url or client_id.","solutions":["Inspect the wrapped %w cause to distinguish the real reason: audience mismatch, token expired, invalid signature, or issuer mismatch.","Verify issuer_url in the Kratos OIDC config matches the provider's issuer exactly (scheme, host, trailing slash).","Ensure the token's aud matches config.ClientID or one of AdditionalIDTokenAudiences (add the right audience if needed).","Check token expiry (exp/nbf claims) and provider clock skew; re-authenticate to obtain a fresh ID token."],"exampleFix":"// before\ncfg := &Configuration{IssuerURL: \"https://provider.example.com/\", ClientID: \"a\"}\n// token aud: \"b\"\n// after\ncfg := &Configuration{IssuerURL: \"https://provider.example.com/\", ClientID: \"b\"}\n// or: cfg.AdditionalIDTokenAudiences = []string{\"b\"}","handlingStrategy":"try-catch","validationCode":"const payload = JSON.parse(atob(idToken.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')))\nif (payload.exp * 1000 < Date.now()) throw new Error('token expired before verification')","typeGuard":null,"tryCatchPattern":"if err != nil {\n    var oerr *oidc.Error\n    if errors.As(err, &oerr) {\n        switch oerr.ErrorType {\n        case oidc.ErrExpired:\n            // re-authenticate\n        default:\n            // check issuer/signature config\n        }\n    }\n}","preventionTips":["Verify issuer_url matches the provider issuer exactly (including trailing slash)","Check token exp/nbf and clock skew before debugging audience errors","Refresh JWKS/provider metadata when keys rotate","Read the wrapped cause (%w) — the aggregate message hides the real reason"],"tags":["oidc","jwt","verification","audience"],"backgroundTag":"jwt-verification-failed","analyzedSha":"b86338da04a040247a07f46100a86dcfb3875909","analyzedAt":"2026-09-07T15:58:15.934Z","contentChangedAt":"2026-09-07T15:58:15.934Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}