{"record":{"id":"7b7f00c3f897d60b","repo":"nats-io/nats-server","slug":"auth-callout-violation-auth-callout-response-is-n","errorCode":null,"errorMessage":"auth callout violation: auth callout response is not for expected user","messagePattern":"auth callout violation: auth callout response is not for expected user","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/auth_callout.go","lineNumber":127,"sourceCode":"\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\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}","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/auth_callout.go#L109-L145","documentation":"This error is raised during authorization-callout processing when the auth callout service returns an authorization response whose Subject does not match the user id (public key) that initiated the request. The server treats a mismatched subject as a protocol/security violation and rejects the authentication. It ensures the callout service cannot authorize a different user than the one being checked.","triggerScenarios":"A client connects and triggers the auth callout; the authorization response (AuthorizationResponse claims) contains a Subject field different from the connecting user's public key passed to the check.","commonSituations":"A misconfigured auth callout service echoing the wrong subject, reusing cached responses across users, signing responses for a different account/user, or a bug where the service derives Subject from the wrong request field.","solutions":["Fix the auth callout service to set Subject in the AuthorizationResponse to the exact public key (user id) from the AuthorizationRequest","Ensure the callout service does not cache or replay responses across different users","Log the expected pub and returned cr.Subject on the callout service side to find the mismatch","Verify the service decodes the request JWT with the correct key so it reads the right user id"],"exampleFix":"// before (callout service)\nresp.Subject = requestUserAccount // wrong field\n// after\nresp.Subject = req.UserNonceClaim / decodedReq.Subject // the connecting user's public key","handlingStrategy":"try-catch","validationCode":"// client side: ensure the callout service sets Subject to your public key\n// server side: nothing to pre-validate; fix in callout service\nif resp.Subject != expectedPubKey {\n    return fmt.Errorf(\"callout subject mismatch: got %s want %s\", resp.Subject, expectedPubKey)\n}","typeGuard":null,"tryCatchPattern":"user, err := s.lookupAccountAuthorization(...) // callout path\nif err != nil && strings.Contains(err.Error(), \"not for expected user\") {\n    log.Errorf(\"callout service returned wrong subject; check callout service config\")\n    return nil, ErrAuthorization\n}","preventionTips":["Callout service must echo the request's subject exactly","Avoid caching/replaying authorization responses across users","Integration-test the callout flow with real user credentials"],"tags":["auth","jwt","callout","security","nats"],"backgroundTag":"auth-callout-subject-mismatch","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}