{"record":{"id":"9ff18186327ab3c2","repo":"cloudflare/cloudflared","slug":"metadata-jwt-is-older-than-s","errorCode":null,"errorMessage":"metadata JWT is older than %s","messagePattern":"metadata JWT is older than (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"token/token.go","lineNumber":513,"sourceCode":"\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to get app info\")\n\t}\n\t_ = resp.Body.Close()\n\n\trawJWT := resp.Header.Get(accessMetadataRespHeader)\n\tif rawJWT == \"\" {\n\t\treturn \"\", fmt.Errorf(\"failed to find Access application at %s\", reqURL)\n\t}\n\treturn rawJWT, nil\n}\n\nfunc validateMetadataIssuedAt(iat int64, now time.Time) error {\n\tif iat <= 0 {\n\t\treturn errors.New(\"metadata JWT iat is missing or invalid\")\n\t}\n\tissuedAt := time.Unix(iat, 0)\n\tif issuedAt.Before(now.Add(-metadataMaxAge)) {\n\t\treturn fmt.Errorf(\"metadata JWT is older than %s\", metadataMaxAge)\n\t}\n\tif issuedAt.After(now.Add(metadataAllowedClockSkew)) {\n\t\treturn fmt.Errorf(\"metadata JWT is more than %s in the future\", metadataAllowedClockSkew)\n\t}\n\treturn nil\n}\n\nfunc handleRedirects(req *http.Request, via []*http.Request, orgToken string) error {\n\t// attach org token to login request\n\tif strings.Contains(req.URL.Path, AccessLoginWorkerPath) {\n\t\treq.AddCookie(&http.Cookie{Name: tokenCookie, Value: orgToken}) //nolint: gosec\n\t}\n\n\t// attach app session cookie to authorized request\n\tif strings.Contains(req.URL.Path, AccessAuthorizedWorkerPath) {\n\t\t// We need to check and see if the CF_APP_SESSION cookie was set\n\t\tfor _, prevReq := range via {\n\t\t\tif prevReq != nil && prevReq.Response != nil {","sourceCodeStart":495,"sourceCodeEnd":531,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/token/token.go#L495-L531","documentation":"validateMetadataIssuedAt enforces freshness of the metadata JWT's `iat` (issued-at) claim. If the token was issued more than metadataMaxAge (24 hours) ago relative to the local clock, GetAppInfo rejects it, because a stale metadata token can no longer be trusted to describe the current Access application.","triggerScenarios":"GetAppInfo parses a metadata JWT whose `iat` is earlier than now minus 24h. Happens when cached or replayed tokens are used, or when the local machine clock is more than 24h ahead of real time so a genuinely fresh token appears old.","commonSituations":"Machine with a badly skewed system clock (VM restored from snapshot, wrong RTC, NTP disabled); a cached metadata JWT stored on disk and reused the next day; replaying an old token captured from logs.","solutions":["Synchronize the system clock (systemctl start ntpd / chronyd, or `w32tm /resync` on Windows) and re-run.","Re-run the command so a fresh metadata JWT is fetched from the edge instead of a cached one.","Clear any persisted token cache (e.g. stored Access tokens under the cloudflared config directory) and log in again.","If clock skew is intentional in your environment, this 24h window cannot be extended without changing the library; keep clocks within NTP tolerance."],"exampleFix":"// before (host with skewed clock)\n$ date; cloudflared access curl https://app.internal.example.com\n// error: metadata JWT is older than 24h0m0s\n// after — resync clock, then retry\n$ sudo chronyc makestep\n$ cloudflared access curl https://app.internal.example.com","handlingStrategy":"validation","validationCode":"// check local clock sanity before calling GetAppInfo\nnow := time.Now()\nresp, _ := http.Get(\"https://www.cloudflare.com/cdn-cgi/trace\")\n// if you parse a Date header or NTP time and |localNow - serverNow| > 1h, fix the clock first\nif skew := time.Since(serverTime); skew > time.Hour || skew < -time.Hour {\n    return fmt.Errorf(\"local clock skewed by %s; synchronize with NTP before fetching metadata\", skew)\n}","typeGuard":null,"tryCatchPattern":"appInfo, err := token.GetAppInfo(authDomain, appURL)\nif err != nil {\n    if strings.Contains(err.Error(), \"older than\") {\n        return fmt.Errorf(\"%w — check system clock and clear cached tokens\", err)\n    }\n    return err\n}","preventionTips":["Keep NTP enabled on hosts and in containers/VMs.","Do not cache metadata JWTs beyond a few hours; always re-fetch.","After restoring a VM from snapshot, resync the clock before running cloudflared.","Monitor clock skew in CI runners that use cloudflared."],"tags":["jwt","clock-skew","time","cloudflare-access"],"backgroundTag":"jwt-token-expired","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"}