Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RequestJS - SSL connection is authorized but getPeerCertificate() returns null

I'm using the node package RequestJS v2.65.0 on node v4.1.2

I'm trying to read the SSL certificate from certain sites (eg. GitHub.com). This previously worked on node 0.12. On node 4.2.1, however, getPeerCertificate() returns null.

For example:

request({
  url: 'https://github.com'
}, function (err, res, body) {
  console.log('err:', err)
  console.log('peerCertificate:',res.req.connection.getPeerCertificate());
  console.log('authorized:',res.req.connection.authorized);
  console.log('authorizationError:',res.req.connection.authorizationError);
});

will print out

err: null
peerCertificate: null
authorized: true
authorizationError: null

i.e. the secure connection is established but the certificate is null.

From my (basic) understanding, if the connection is authorized, there should be a peer certificate.

I've tried with a number of SSL sites, and the result is the same. Is there an option in request, a bug with Node 4, or a misunderstanding on my part about how SSL/TLS works in node?

like image 695
George Avatar asked Oct 29 '25 14:10

George


2 Answers

I think your problem is because the getPeerCertificate() will only output anything when the connection is in connected state, but when you receive your response, it's likely already too late.

If you want getPeerCertificate to output, you should do it at the TLS level independently as such:

const socket = require('tls').connect(443, "github.com", () => {
  console.log('client connected',
    socket.authorized ? 'authorized' : 'unauthorized');
  process.stdin.pipe(socket);
  process.stdin.resume();
});

Important! : Do not put the protocol in the URL. Rather, use require('url').parse(yourURL).hostname as the target.

More info and example here: https://nodejs.org/api/tls.html#tls_tls_connect_port_host_options_callback

like image 138
nembleton Avatar answered Oct 31 '25 05:10

nembleton


@nembleton is correct about why this happens. There's an issue for this at https://github.com/request/request/issues/1867

Rather than dropping down to raw TLS sockets, you can stick with Request and use its stream API. This approach is particularly useful if you're taking advantage of other Request features that would make the low-level connection more complicated (e.g. going through an HTTPS proxy).

The code snippet in the original question becomes:

request({
  url: 'https://github.com'
})
.on('error', function(err) {
    console.log('err:', err);
})
.on('response', function (res) {
  console.log('peerCertificate:',res.socket.getPeerCertificate());
  console.log('authorized:',res.socket.authorized);
  console.log('authorizationError:',res.socket.authorizationError);
});

(I used res.socket rather than res.req.connection for brevity/directness, but either will work.)

like image 27
hgcummings Avatar answered Oct 31 '25 05:10

hgcummings



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!