{"record":{"id":"eb5ca4a82a8ab6bd","repo":"nats-io/nats-server","slug":"wrong-issuer-for-auth-callout-response-on-account","errorCode":null,"errorMessage":"wrong issuer for auth callout response on account %q, expected %q got %q","messagePattern":"wrong issuer for auth callout response on account %q, expected %q got %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/auth_callout.go","lineNumber":182,"sourceCode":"\t\t\t// Operator mode is who we send the request on unless switching accounts.\n\t\t\tissuer = acc.Name\n\t\t}\n\n\t\t// the jwt issuer can be a signing key\n\t\tjwtIssuer := arc.Issuer\n\t\tif arc.IssuerAccount != _EMPTY_ {\n\t\t\tif !isOperatorMode {\n\t\t\t\t// this should be invalid - effectively it would allow the auth callout\n\t\t\t\t// to issue on another account which may be allowed given the configuration\n\t\t\t\t// where the auth callout account can handle multiple different ones..\n\t\t\t\treturn _EMPTY_, fmt.Errorf(\"error non operator mode account %q: attempted to use issuer_account\", account)\n\t\t\t}\n\t\t\tjwtIssuer = arc.IssuerAccount\n\t\t}\n\n\t\tif jwtIssuer != issuer {\n\t\t\tif !isOperatorMode {\n\t\t\t\treturn _EMPTY_, fmt.Errorf(\"wrong issuer for auth callout response on account %q, expected %q got %q\", account, issuer, jwtIssuer)\n\t\t\t} else if !acc.isAllowedAcount(jwtIssuer) {\n\t\t\t\treturn _EMPTY_, fmt.Errorf(\"account %q not permitted as valid account option for auth callout for account %q\",\n\t\t\t\t\tarc.Issuer, account)\n\t\t\t}\n\t\t}\n\t\treturn jwtIssuer, nil\n\t}\n\n\tgetExpirationAndAllowedConnections := func(arc *jwt.UserClaims, account string) (time.Duration, map[string]struct{}, error) {\n\t\tallowNow, expiration := validateTimes(arc)\n\t\tif !allowNow {\n\t\t\tc.Errorf(\"Outside connect times\")\n\t\t\treturn 0, nil, fmt.Errorf(\"authorized user on account %q outside of valid connect times\", account)\n\t\t}\n\n\t\tallowedConnTypes, err := convertAllowedConnectionTypes(arc.User.AllowedConnectionTypes)\n\t\tif err != nil {\n\t\t\tc.Debugf(\"%v\", err)","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/auth_callout.go#L164-L200","documentation":"In non-operator mode, the Issuer of the auth callout response's user JWT does not match the expected issuer (the account/signing key the server expects for that account). The server rejects the response because the JWT was not signed by the authorized identity. This prevents a callout from minting users attributed to another issuer.","triggerScenarios":"The callout signs the user JWT with a signing key/nkey different from the account's expected issuer while the server runs in non-operator mode, so jwtIssuer != issuer.","commonSituations":"Callout configured with the wrong signing key or signing with the callout account key instead of the target account's key; rotating keys on the account without updating the callout.","solutions":["Sign the user JWT with the issuer (account or its signing key) the server expects for the target account.","Update the callout's configured signing key to match the account's current issuer after a key rotation.","Check the error's expected/got values and align the callout's key selection.","If multiple issuers are intended, switch to operator mode where allowed-account checks apply instead."],"exampleFix":"// before\nsigned, err := arc.Encode(calloutServiceNkey)\n// after\nsigned, err := arc.Encode(targetAccountIssuerNkey) // must equal the account's issuer in non-operator mode","handlingStrategy":"validation","validationCode":"if jwtIssuer := arc.Issuer; jwtIssuer != expectedIssuer {\n    return fmt.Errorf(\"issuer %q != expected %q\", jwtIssuer, expectedIssuer)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure the callout with the exact issuer the server expects per account.","Re-verify signing keys after any account key rotation.","Compare 'expected' vs 'got' in the error message when debugging."],"tags":["auth-callout","jwt","issuer"],"backgroundTag":"auth-callout-issuer-mismatch","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}