Debugging Node.js mTLS Client: “Self-signed certificate in certificate chain”
Debugging Node.js mTLS Client: “Self-signed certificate in certificate chain”
When making an API request from a Node.js client to a server that enforces mutual TLS (mTLS), you might encounter this error:
[cause]: Error: self-signed certificate in certificate chain
at TLSSocket.onConnectSecure (node:_tls_wrap:1679:34)
at TLSSocket.emit (node:events:518:28)
at TLSSocket._finishInit (node:_tls_wrap:1078:8)
at ssl.onhandshakedone (node:_tls_wrap:864:12) {
code: 'SELF_SIGNED_CERT_IN_CHAIN'
}
Understanding the Issue
This error typically occurs when the client cannot fully verify the server’s certificate chain. In mTLS, both client and server need to trust each other’s root CA certificates. If any root in the chain is missing from the client’s CA bundle, the handshake fails.
Step 1: Inspect the Server Certificate Chain
You can use OpenSSL to see the full server chain:
openssl s_client -connect server.example.com:443 -showcerts
This will display all certificates sent by the server, including intermediate and root certificates. Check if the root CA is included in your client ca.pem file.
Step 2: Enable Node.js TLS Debug Logging
To get more insight into the TLS handshake in Node.js, enable debug logs:
NODE_DEBUG=tls,https,net node app.js
This can help identify which certificate is causing the verification failure.
Step 3: Verify mTLS Requirements
- Both client and server must trust each other’s root CA chains.
- If any root certificate is missing, the TLS handshake fails.
- This applies to Node.js clients as well as Spring Boot or other server-side clients.
Step 4: Apply the Fix
In my case, the client CA bundle (ca.pem) was missing one root CA from the server chain. Adding that root certificate resolved the handshake issue immediately:
cat server_root_ca.pem >> ca.pem
After updating the CA bundle, the Node.js client successfully established an mTLS connection with the server.
Key Takeaways
- Always verify the server certificate chain with OpenSSL before troubleshooting mTLS issues.
- Enable
NODE_DEBUG=tls,https,netfor detailed handshake logs in Node.js. - Ensure that both client and server trust each other’s root CAs for mTLS.
- This debugging pattern works for other clients, including Spring Boot apps.
Following these steps can save hours of frustration when dealing with self-signed certificate errors in mTLS environments.
❤️ Support This Blog
If this post helped you, you can support my writing with a small donation. Thank you for reading.
Comments
Post a Comment