Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js: access the client certificate

Tags:

node.js

ssl

I'm working on a Node.js app that we will call "server A" where users have to provide a client certificate in order to access services.

Simplified example:

/** server setup **/
var serverOptions = {
    key: fs.readFileSync('certs/server.key'),
    cert: fs.readFileSync('certs/server.crt'),
    ca: [fs.readFileSync('certs/ca.crt'), fs.readFileSync('certs/bar.cer'), fs.readFileSync('certs/foo.cer')],
    requestCert: true
};

https.createServer(serverOptions, app).listen(SERVER_PORT, '', null, function () {
    var host = this.address().address;
    var port = this.address().port;

    console.log('listening at http://%s:%s', host, port);
});

Everything works as expected, the following code prints the details of the client certificate.

app.get('/', function (req, res) {

    /*** Dump ***/
    res.contentType('application/json');
    res.send(util.inspect(req.socket.getPeerCertificate(true), {colors: true}));

});

However, I would like to be able to use this client certificate obtained in serverA, to make a request to another server called "server B".

options = {
    hostname: 'localhost',
    port: '3010',
    path: '/',
    method: 'POST',
    headers: {
        'Content-Type': 'text/xml;charset=UTF-8',
        'Content-Length': serverResponse.length,
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 
    },
    cert: clientCertificate
};

var req = https.request(options, function (res) {

    console.log('statusCode: ', res.statusCode);
    console.log('headers: ', res.headers);

    res.on('data', function(d) {
        callback(d);
    });
});

The problem is that I have not found a way to get a proper X509 certificate with the getPeerCertificate function, which returns a "custom" object representation of the certificate. As described in the official documentation, the cert parameter must be provided with the following data :

Public x509 certificate to use. Default null.

Is there a way to get the client certificate in the correct format for that purpose?

like image 203
Konal Avatar asked May 12 '15 15:05

Konal


1 Answers

I had the same problem and saw your question with no answers, so I'm coming back to post my solution.

The certificate object has a raw field which contains the certificate data you want in byte form. To get it in X509 format, just convert it to base64. So the code you're looking for is:

req.socket.getPeerCertificate(true).raw.toString('base64');

Hope that helps!

like image 104
Hussain Avatar answered Oct 13 '22 16:10

Hussain