{"record":{"id":"66f394ee399277b6","repo":"cloudflare/cloudflared","slug":"cached-token-audience-does-not-include-expected-ap","errorCode":null,"errorMessage":"cached token audience does not include expected application audience %q","messagePattern":"cached token audience does not include expected application audience %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"token/token.go","lineNumber":630,"sourceCode":"\ttoken, err := getTokenIfExists(path)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tvar payload jwtPayload\n\terr = json.Unmarshal(token.UnsafePayloadWithoutVerification(), &payload)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tif payload.isExpired() {\n\t\terr := os.Remove(path)\n\t\treturn \"\", err\n\t}\n\tif !slices.Contains(payload.Aud, appInfo.AppAUD) {\n\t\tif err := os.Remove(path); err != nil && !os.IsNotExist(err) {\n\t\t\treturn \"\", fmt.Errorf(\"failed to remove cached token with unexpected audience: %w\", err)\n\t\t}\n\t\treturn \"\", fmt.Errorf(\"cached token audience does not include expected application audience %q\", appInfo.AppAUD)\n\t}\n\n\treturn token.CompactSerialize()\n}\n\n// GetTokenIfExists will return the token from local storage if it exists and not expired\nfunc getTokenIfExists(path string) (*jose.JSONWebSignature, error) {\n\tcontent, err := os.ReadFile(path) // nolint: gosec\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttoken, err := jose.ParseSigned(string(content), signatureAlgs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn token, nil\n}\n","sourceCodeStart":612,"sourceCodeEnd":648,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/token/token.go#L612-L648","documentation":"The cached Access token's aud (audience) claim does not contain the audience of the application being accessed (appInfo.AppAUD). cloudflared rejects tokens issued for a different Access application rather than replaying them, and returns this error after (best-effort) removing the stale cache entry. The user must obtain a fresh token for the correct application.","triggerScenarios":"Calling GetAppTokenIfExists (via login, curl, or generateToken) when the token cached on disk was minted for a different Cloudflare Access application (its Aud list lacks appInfo.AppAUD).","commonSituations":"User logged into app A earlier, then runs cloudflared access curl against app B which shares the same cache location; AppAUD changed server-side after token issuance; misconfigured appAUD flag in the local config.","solutions":["Run `cloudflared access login <url>` again to mint a token for the correct application.","Verify the configured AppAUD matches the Access application in the Cloudflare dashboard.","Clear the token cache directory so the stale token is not re-read."],"exampleFix":"// before\nappInfo := globalAppInfo // AppAUD from a previous/different app\n// after\ncloudflared access login https://app.example.com // refresh token for the correct appAUD","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"token, err := token.GetAppTokenIfExists(appInfo)\nif err != nil {\n    if strings.Contains(err.Error(), \"audience does not include\") {\n        token, err = login(appInfo) // fallback: fetch a fresh token\n    }\n    if err != nil { return err }\n}","preventionTips":["Always re-login when switching between Access applications","Verify AppAUD configuration against the Cloudflare dashboard","Automatically clear the token cache on audience-mismatch errors"],"tags":["jwt","audience-mismatch","token-cache"],"backgroundTag":"jwt-audience-mismatch","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}