{"record":{"id":"7065eed020b92360","repo":"nats-io/nats-server","slug":"auth-callout-cannot-be-configured-in-fips-140-mo","errorCode":null,"errorMessage":"'auth_callout' cannot be configured in FIPS-140 mode","messagePattern":"'auth_callout' cannot be configured in FIPS-140 mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/opts.go","lineNumber":4624,"sourceCode":"\t\t\tauth.timeout = at\n\t\tcase \"users\":\n\t\t\tnkeys, users, err := parseUsers(tk, errors)\n\t\t\tif err != nil {\n\t\t\t\t*errors = append(*errors, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tauth.users = users\n\t\t\tauth.nkeys = nkeys\n\t\tcase \"default_permission\", \"default_permissions\", \"permissions\":\n\t\t\tpermissions, err := parseUserPermissions(tk, errors)\n\t\t\tif err != nil {\n\t\t\t\t*errors = append(*errors, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tauth.defaultPermissions = permissions\n\t\tcase \"auth_callout\", \"auth_hook\":\n\t\t\tif fips140.Enabled() {\n\t\t\t\t*errors = append(*errors, fmt.Errorf(\"'auth_callout' cannot be configured in FIPS-140 mode\"))\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tac, err := parseAuthCallout(tk, errors)\n\t\t\tif err != nil {\n\t\t\t\t*errors = append(*errors, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tauth.callout = ac\n\t\tcase \"proxy_required\":\n\t\t\tauth.proxyRequired = mv.(bool)\n\t\tdefault:\n\t\t\tif !tk.IsUsedVariable() {\n\t\t\t\terr := &unknownConfigFieldErr{\n\t\t\t\t\tfield: mk,\n\t\t\t\t\tconfigErr: configErr{\n\t\t\t\t\t\ttoken: tk,\n\t\t\t\t\t},\n\t\t\t\t}","sourceCodeStart":4606,"sourceCodeEnd":4642,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/opts.go#L4606-L4642","documentation":"When parsing server options (config file), an 'auth_callout' or 'auth_hook' block is rejected if FIPS-140 mode is enabled (fips140.Enabled()). Auth callout relies on crypto not approved for FIPS-140, so the combination is explicitly disallowed and the server reports this error during option parsing.","triggerScenarios":"Starting nats-server with both a FIPS-140 configuration (e.g. fips_140: true / GODELIBRYPTO-style mode) and an 'auth_callout' (or legacy 'auth_hook') block in the server config.","commonSituations":"Enabling FIPS mode for compliance while an existing config still contains an auth_callout section; migrating a config with auth_callout onto FIPS-hardened deployments; operator unaware auth_callout is unsupported under FIPS-140.","solutions":["Remove the auth_callout/auth_hook block from the config, or disable FIPS-140 mode — the two cannot coexist","Replace auth callout with NKeys/JWT-based (decentralized) authentication compatible with FIPS mode","Use an external auth proxy instead of auth_callout in FIPS deployments","Check fips140.Enabled() settings (build/env) to confirm why FIPS mode is active"],"exampleFix":"// before (config)\nfips_140: true\nauth_callout {\n  issuer: \"...\"\n  auth_users: [\"svc\"]\n}\n// after\nfips_140: true\n# auth_callout removed; use accounts/NKeys instead","handlingStrategy":"validation","validationCode":"if fips140.Enabled() {\n\tif hasAuthCallout(cfg) {\n\t\tlog.Fatal(\"auth_callout is not allowed in FIPS-140 mode\")\n\t}\n}","typeGuard":"func authCalloutAllowed(fips bool, cfg map[string]any) bool {\n\t_, hasCallout := cfg[\"auth_callout\"]\n\treturn !(fips && hasCallout)\n}","tryCatchPattern":"if err := server.ProcessConfigFile(path); err != nil {\n\tif strings.Contains(err.Error(), \"FIPS\") {\n\t\tlog.Fatal(\"remove auth_callout or disable FIPS-140 mode\")\n\t}\n}","preventionTips":["Audit configs for auth_callout before enabling FIPS-140 mode","Plan FIPS-compliant auth alternatives (NKeys, JWTs) in advance","Document that auth_callout and FIPS-140 are mutually exclusive"],"tags":["config","fips","auth-callout"],"backgroundTag":"feature-incompatible-with-fips","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}