{"record":{"id":"bfd5c3520d10c7b6","repo":"cloudflare/cloudflared","slug":"token-is-invalid-s","errorCode":null,"errorMessage":"token is invalid: %s","messagePattern":"token is invalid: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"validation/validation.go","lineNumber":198,"sourceCode":"\t}\n\n\tissuerURL, err := validateUrlString(issuer)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// An issuerURL from Cloudflare Access will always use HTTPS.\n\tissuerURL = strings.Replace(issuerURL, \"http:\", \"https:\", 1)\n\n\tkeySet := oidc.NewRemoteKeySet(ctx, domainURL+accessCertPath)\n\treturn &Access{oidc.NewVerifier(issuerURL, keySet, &oidc.Config{ClientID: applicationAUD})}, nil\n}\n\nfunc (a *Access) Validate(ctx context.Context, jwt string) error {\n\ttoken, err := a.verifier.Verify(ctx, jwt)\n\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"token is invalid: %s\", jwt)\n\t}\n\n\t// Perform extra sanity checks, just to be safe.\n\n\tif token == nil {\n\t\treturn fmt.Errorf(\"token is nil: %s\", jwt)\n\t}\n\n\tif !strings.HasSuffix(token.Issuer, accessDomain) {\n\t\treturn fmt.Errorf(\"token has non-cloudflare issuer of %s: %s\", token.Issuer, jwt)\n\t}\n\n\treturn nil\n}\n\nfunc (a *Access) ValidateRequest(ctx context.Context, r *http.Request) error {\n\treturn a.Validate(ctx, r.Header.Get(accessJwtHeader))\n}","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/validation/validation.go#L180-L216","documentation":"This error is returned by Access.Validate when the JWT verifier (a.verifier.Verify) rejects the presented Access token. It wraps the underlying verification error (bad signature, expired token, wrong audience, malformed JWT) together with the offending token string. It means the token cannot be trusted and the request must be rejected.","triggerScenarios":"ValidateRequest passes a request's Cf-Access-Jwt-Assertion JWT to Access.Validate, and verifier.Verify fails: token expired, signature invalid, signed by an unexpected team cert, wrong AUD tag, or token truncated/corrupted in transit.","commonSituations":"User's Access session expired and the browser still sends the old JWT; application AUD changed after config edits; token copied between applications with different audiences; clock skew between validating host and Cloudflare edge; tokens forwarded incorrectly by a proxy.","solutions":["Have the user re-authenticate to the Access application to obtain a fresh JWT","Verify the application's AUD tag configured in the validator matches the one in the token (jwt.io decode of the payload)","Confirm the machine's clock is synchronized (NTP) to avoid expiry misjudgment","Ensure the token header is forwarded intact (not stripped by a proxy/load balancer)","Check that the team's public keys/certs used by the verifier are current"],"exampleFix":"// before: treating any validate error as fatal misconfiguration\nif err := validator.Validate(ctx, jwt); err != nil {\n\tpanic(err)\n}\n// after: distinguish expired token (re-auth needed) from other failures\nif err := validator.Validate(ctx, jwt); err != nil {\n\tlog.Warn().Err(err).Msg(\"access token rejected, requiring re-authentication\")\n\thttp.Error(w, \"unauthorized: please re-authenticate via Cloudflare Access\", http.StatusUnauthorized)\n\treturn\n}","handlingStrategy":"try-catch","validationCode":"parts := strings.Split(jwt, \".\")\nif len(parts) != 3 {\n\treturn errors.New(\"malformed JWT: expected 3 dot-separated segments\")\n}\n// decode payload to pre-check exp and aud before Validate\npayload, _ := base64.RawURLEncoding.DecodeString(parts[1])\nvar claims struct{ Exp int64 `json:\"exp\"`; Aud []string `json:\"aud\"` }\njson.Unmarshal(payload, &claims)\nif time.Now().Unix() > claims.Exp {\n\treturn errors.New(\"token already expired; re-authenticate\")\n}","typeGuard":null,"tryCatchPattern":"if err := validator.Validate(ctx, jwt); err != nil {\n\tvar httpErr *httpError\n\tlog.Warn().Err(err).Msg(\"access JWT rejected\")\n\thttp.Error(w, \"unauthorized\", http.StatusUnauthorized)\n\treturn\n}","preventionTips":["Prompt re-authentication when tokens are near expiry","Keep verifier AUD/team config in sync with the Access application","Synchronize clocks with NTP on validating hosts","Ensure proxies forward the Cf-Access-Jwt-Assertion header unchanged"],"tags":["jwt","authentication","token","security"],"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-14T00:17:10.932Z"}