Cuz Cuz - 4 months ago 309
Node.js Question

Nodejs https request UNABLE_TO_GET_ISSUER_CERT_LOCALLY

OS: debian sid

Nodejs: v0.10.38

I have a request to a private service that use authentication:



var https = require('https');

var options = {
host: 'private.service.com',
path: '/accounts/' + '123323' + '/orders',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': 0,
'Authorization': 'Bearer ' + 'asdsdgcvxcvxcv'
}
};

var request = https.request(options, function (res) {
console.log(res);
});





When i run the script, node throws this error:

events.js:72
throw er; // Unhandled 'error' event
^
Error: UNABLE_TO_GET_ISSUER_CERT_LOCALLY
at SecurePair.<anonymous> (tls.js:1381:32)
at SecurePair.emit (events.js:92:17)
at SecurePair.maybeInitFinished (tls.js:980:10)
at CleartextStream.read [as _read] (tls.js:472:13)
at CleartextStream.Readable.read (_stream_readable.js:341:10)
at EncryptedStream.write [as _write] (tls.js:369:25)
at doWrite (_stream_writable.js:226:10)
at writeOrBuffer (_stream_writable.js:216:5)
at EncryptedStream.Writable.write (_stream_writable.js:183:11)
at write (_stream_readable.js:602:24)


The same exact script worked well for months, and i'm sure the authentication is correct. Today is the first time i have this situation.

Which can be the cause for this error?

Answer

There is a reason for SSL. Besides other features, it authenticates that you are really communicating with the server identified by private.service.com hostname. Otherwise your client software can be cheated by a Man-in-the-Middle attack.

First when anyone encounters this issue, they should update system root SSL certificates. In Debian they are contained in ca-certificates apt-get package.

If it doesn't help, the server probably uses an issuer certificate, which is not trusted by default worldwide PKI infrastructure. In this case the client should compare the certificate public key signature with a preshared value. This is known as "certificate pinning".

Specifically to your error, if it worked before, it is possible that the server certificate has expired. The server should renew it. As a temporary solution, you can turn off PKI validation by rejectUnauthorized option. However you should use it together with the pinning approach. In NodeJS, you can get the server certificate fingerprint from res.socket.getPeerCertificate().fingerprint.

Comments