{"record":{"id":"9a33d2b8abbeb588","repo":"nats-io/nats-server","slug":"authorization-response-had-validation-errors-v","errorCode":null,"errorMessage":"authorization response had validation errors: %v","messagePattern":"authorization response had validation errors: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/auth_callout.go","lineNumber":122,"sourceCode":"\t\t// If we sent an encrypted request the response could be encrypted as well.\n\t\t// we are expecting the input to be `eyJ` if it is a JWT\n\t\tif xkp != nil && len(msg) > 0 && !bytes.HasPrefix(msg, []byte(jwtPrefix)) {\n\t\t\tvar err error\n\t\t\tmsg, err = xkp.Open(msg, pubAccXKey)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"error decrypting auth callout response on account %q: %v\", account, err)\n\t\t\t}\n\t\t\tencrypted = true\n\t\t}\n\n\t\tcr, err := jwt.DecodeAuthorizationResponseClaims(string(msg))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvr := jwt.CreateValidationResults()\n\t\tcr.Validate(vr)\n\t\tif len(vr.Issues) > 0 {\n\t\t\treturn nil, fmt.Errorf(\"authorization response had validation errors: %v\", vr.Issues[0])\n\t\t}\n\n\t\t// the subject is the user id\n\t\tif cr.Subject != pub {\n\t\t\treturn nil, errors.New(\"auth callout violation: auth callout response is not for expected user\")\n\t\t}\n\n\t\t// check the audience to be the server ID\n\t\tif cr.Audience != s.info.ID {\n\t\t\treturn nil, errors.New(\"auth callout violation: auth callout response is not for server\")\n\t\t}\n\n\t\t// check if had an error message from the auth account\n\t\tif cr.Error != _EMPTY_ {\n\t\t\treturn nil, fmt.Errorf(\"auth callout service returned an error: %v\", cr.Error)\n\t\t}\n\n\t\t// if response is encrypted none of this is needed","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/auth_callout.go#L104-L140","documentation":"The server validated the authorization response claims (AuthorizationResponseClaims, cr) returned by an auth callout service using jwt.CreateValidationResults/Validate, and at least one generic JWT claim was invalid (only the first issue is reported). This is thrown when the callout's response JWT fails structural/temporal validation (e.g. expired, malformed claims) before the server will trust it. The auth callout contract requires a well-formed, currently valid response JWT.","triggerScenarios":"An auth callout service publishes an AuthorizationResponseClaims JWT whose Validate() reports issues: expired or not-yet-valid nbf, missing/invalid issuer or subject, bad times format, or a claim violating jwt generic claim rules.","commonSituations":"Callout service clock skew producing expired/early JWTs; callout built against an older JWT library emitting claims the server's jwt package rejects; hand-rolled claim construction leaving required fields empty.","solutions":["Sync the callout service's clock (NTP) so issued JWTs are temporally valid.","Log vr.Issues server-side or replicate cr.Validate(vr) in the callout to see the exact failing claim and fix claim construction.","Ensure the callout library/jwt package version matches what the server validates against.","Set proper Issuer, Subject, Audience and times in the AuthorizationResponseClaims before signing."],"exampleFix":"// before\ncr := jwt.NewAuthorizationResponseClaims(pub, issuer)\ncr.Expires = time.Now().Add(-time.Minute) // stale/expired\n// after\ncr := jwt.NewAuthorizationResponseClaims(pub, issuer)\ncr.Expires = time.Now().Add(2 * time.Minute)\nvr := jwt.CreateValidationResults()\ncr.Validate(vr)\nif len(vr.Issues) > 0 { /* fix claims before publishing */ }","handlingStrategy":"validation","validationCode":"vr := jwt.CreateValidationResults()\ncr.Validate(vr)\nif len(vr.Issues) > 0 {\n    return fmt.Errorf(\"response claims invalid: %v\", vr.Issues)\n}","typeGuard":null,"tryCatchPattern":"resp, err := doAuthCallout()\nif err != nil {\n    var verr *ValidationErr\n    if errors.As(err, &verr) { /* regenerate claims, resync clock */ }\n    return err\n}","preventionTips":["Validate claims with cr.Validate(vr) in the callout before publishing.","Run NTP on all hosts issuing and validating JWTs.","Keep the jwt library version in the callout in sync with the server."],"tags":["jwt","auth-callout","validation"],"backgroundTag":"jwt-claim-validation-failed","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}