{"record":{"id":"37488b604b6bfe7b","repo":"nats-io/nats-server","slug":"ocsp-peer-verification-for-client-connections-requ","errorCode":null,"errorMessage":"OCSP peer verification for client connections requires TLS verify (mTLS) to be enabled","messagePattern":"OCSP peer verification for client connections requires TLS verify \\(mTLS\\) to be enabled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/ocsp_peer.go","lineNumber":152,"sourceCode":"\treturn chains[0][0]\n}\n\n// plugTLSOCSPPeer will plug the TLS handshake lifecycle for client mTLS connections and Leaf connections\nfunc (s *Server) plugTLSOCSPPeer(config *tlsConfigKind) (*tls.Config, bool, error) {\n\tif config == nil || config.tlsConfig == nil {\n\t\treturn nil, false, errors.New(certidp.ErrUnableToPlugTLSEmptyConfig)\n\t}\n\tkind := config.kind\n\tisSpoke := config.isLeafSpoke\n\ttcOpts := config.tlsOpts\n\tif tcOpts == nil || tcOpts.OCSPPeerConfig == nil || !tcOpts.OCSPPeerConfig.Verify {\n\t\treturn nil, false, nil\n\t}\n\ts.Debugf(certidp.DbgPlugTLSForKind, config.kind)\n\t// peer is a tls client\n\tif kind == kindStringMap[CLIENT] || (kind == kindStringMap[LEAF] && !isSpoke) {\n\t\tif !tcOpts.Verify {\n\t\t\treturn nil, false, errors.New(certidp.ErrMTLSRequired)\n\t\t}\n\t\treturn s.plugClientTLSOCSPPeer(config)\n\t}\n\t// peer is a tls server\n\tif kind == kindStringMap[LEAF] && isSpoke {\n\t\treturn s.plugServerTLSOCSPPeer(config)\n\t}\n\treturn nil, false, nil\n}\n\nfunc (s *Server) plugClientTLSOCSPPeer(config *tlsConfigKind) (*tls.Config, bool, error) {\n\tif config == nil || config.tlsConfig == nil || config.tlsOpts == nil {\n\t\treturn nil, false, errors.New(certidp.ErrUnableToPlugTLSClient)\n\t}\n\ttc := config.tlsConfig\n\ttcOpts := config.tlsOpts\n\tkind := config.kind\n\tif tcOpts.OCSPPeerConfig == nil || !tcOpts.OCSPPeerConfig.Verify {","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/ocsp_peer.go#L134-L170","documentation":"Raised in Server.plugTLSOCSPPeer (server/ocsp_peer.go:152) when OCSP peer verification is requested for client (or non-spoke leaf) connections but the TLS config does not set verify (mutual TLS). The VerifyConnection hook inspects peer verified chains, which only exist when the server requests and verifies client certificates; certidp.ErrMTLSRequired is returned so startup fails instead of silently verifying nothing.","triggerScenarios":"Config defines ocsp_peer { verify: true } under a TLS block for CLIENT connections (or LEAF connections where the server is not the spoke) while tls verify (i.e. ca_file-based mTLS client cert verification) is absent or false.","commonSituations":"Enabling OCSP peer checks but forgetting ca_file / verify: true in the tls block; leaf-node setups where the spoke/s Hub roles are confused so the server-side path is chosen; documenting mTLS elsewhere but leaving the leaf's TLS block client-auth-free.","solutions":["Enable mTLS in the same TLS block: set verify: true and provide ca_file so client certificates are required and verified","For leaf connections, ensure the topology matches: OCSP peer verification of servers applies to the spoke side; use client-side (hub) config where appropriate","Re-test the handshake with a client certificate to confirm mTLS is enforced before OCSP hooks engage"],"exampleFix":"# before\ntls {\n  cert_file: \"./server-cert.pem\"\n  key_file: \"./server-key.pem\"\n}\nocsp_peer { verify: true }\n# after: mTLS required for OCSP peer verification\ntls {\n  cert_file: \"./server-cert.pem\"\n  key_file: \"./server-key.pem\"\n  ca_file: \"./ca.pem\"\n  verify: true\n}\nocsp_peer { verify: true }","handlingStrategy":"validation","validationCode":"# preflight check: OCSP peer verify requires mTLS (verify: true + ca_file) in the same tls block\nif ocsp_peer.get('verify') and not (tls.get('verify') and tls.get('ca_file')):\n    raise SystemExit('ocsp_peer.verify requires tls verify (mTLS) with ca_file')","typeGuard":null,"tryCatchPattern":"// Go: wrap server start and explain the mTLS requirement\nif err := srv.Start(); err != nil && strings.Contains(err.Error(), \"OCSP peer verification\") && strings.Contains(err.Error(), \"mTLS\") {\n    log.Fatalf(\"Enable mTLS (verify: true + ca_file) before OCSP peer verification: %v\", err)\n}","preventionTips":["Never enable ocsp_peer.verify without also enabling client-certificate verification (ca_file + verify: true)","For leaf nodes, confirm spoke vs hub direction so the OCSP plugging path matches your topology","Test the handshake with and without a client certificate to verify mTLS is actually enforced"],"tags":["tls","mtls","ocsp","config","nats-server"],"backgroundTag":"mtls-required","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}