{"record":{"id":"8652363afd80584d","repo":"nats-io/nats-server","slug":"auth-callout-violation-auth-callout-response-is-n-865236","errorCode":null,"errorMessage":"auth callout violation: auth callout response is not for server","messagePattern":"auth callout violation: auth callout response is not for server","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/auth_callout.go","lineNumber":132,"sourceCode":"\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\n\t\tif isOperatorMode && !encrypted {\n\t\t\tpkStr := cr.Issuer\n\t\t\tif cr.IssuerAccount != _EMPTY_ {\n\t\t\t\tpkStr = cr.IssuerAccount\n\t\t\t}\n\t\t\tif pkStr != account {\n\t\t\t\tif _, ok := acc.hasIssuer(pkStr); !ok {\n\t\t\t\t\treturn nil, errors.New(\"auth callout signing key is unknown\")\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/auth_callout.go#L114-L150","documentation":"This error is raised during auth callout processing when the authorization response's Audience does not equal the server's ID (s.info.ID). The audience check prevents a response intended for one server from being replayed against another. A mismatched audience means the response was not issued for this server and authentication is rejected.","triggerScenarios":"A client connects, the auth callout service responds, but the AuthorizationResponse's Audience field differs from the receiving server's server ID.","commonSituations":"Hardcoded or wrong Audience in the callout service config, responses reused across clustered servers with different IDs, or server ID changes after restart/upgrade while the service caches responses.","solutions":["Set the response Audience to the server ID taken from the AuthorizationRequest's ServerID (or Audience) field, not a static value","Make the callout service derive Audience per-request instead of hardcoding it","If running a cluster, ensure each server gets responses issued with its own server ID (no cross-server response reuse)","Clear any cached authorization responses after server ID changes"],"exampleFix":"// before\nresp.Audience = \"my-server\" // hardcoded\n// after\nresp.Audience = req.Server.ID // server ID from the incoming AuthorizationRequest","handlingStrategy":"try-catch","validationCode":"// callout service: derive audience from the request\nif req.Server.ID == \"\" {\n    return fmt.Errorf(\"no server id in authorization request\")\n}\nresp.Audience = req.Server.ID","typeGuard":null,"tryCatchPattern":"user, err := s.lookupAccountAuthorization(...)\nif err != nil && strings.Contains(err.Error(), \"not for server\") {\n    log.Errorf(\"callout audience mismatch; response not issued for server %s\", s.info.ID)\n    return nil, ErrAuthorization\n}","preventionTips":["Never hardcode the server ID in callout service config","Re-derive Audience per request from the incoming AuthorizationRequest","Invalidate cached responses when server IDs change (upgrades, cluster changes)"],"tags":["auth","jwt","callout","security","nats"],"backgroundTag":"auth-callout-audience-mismatch","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}