6

So, the title is pretty straightforward. I want to consume a web service from a company and I got .cer and .p12 files. Supposedly, I should use .p12 when making a request. I've imported .cer into windows and I can make requests with postman easily. But when I'm trying to do a request with node.js, I get errors. Here's the code, I'm using request module:

var headersOpt = {
    "content-type": "application/json",
};

var options = {
    url: 'https://some-url/api',
    cert: fs.readFileSync(__dirname + '/certs/myCert.p12'),
    headers: headersOpt
};

request.get(options, (error, response, body) => {
    console.log(error);
    console.log(response);
    console.log(body);
});

I get this error:

{ Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
    at Object.createSecureContext (_tls_common.js:89:17)
    at Object.exports.connect (_tls_wrap.js:1048:48)
    at Agent.createConnection (https.js:111:22)
    at Agent.createSocket (_http_agent.js:224:26)
    at Agent.addRequest (_http_agent.js:192:10)
    at new ClientRequest (_http_client.js:256:16)
    at Object.request (http.js:39:10)
    at Object.request (https.js:239:15)
    at Request.start (D:\parser\node_modules\request\request.js:748:32)
    at Request.end (D:\parser\node_modules\request\request.js:1512:10)
  opensslErrorStack:
   [ 'error:140DC009:SSL routines:SSL_CTX_use_certificate_chain_file:PEM lib' ] }
Bertrand Martel
  • 42,756
  • 16
  • 135
  • 159
uglycode
  • 3,022
  • 6
  • 29
  • 55

2 Answers2

17

Use pfx property in agentOptions for pkcs12 format :

'use strict';

const request = require('request');
const fs = require('fs');

var options = {
    url: 'https://some-url/api',
    headers: {
        "content-type": "application/json",
    },
    agentOptions: {
        pfx: fs.readFileSync(__dirname + '/certs/myCert.p12'),
        passphrase: ''
    }
};

request.get(options, (error, response, body) => {
    console.log(error);
    console.log(response);
    console.log(body);
});

If your certificate is self signed, check this

Bertrand Martel
  • 42,756
  • 16
  • 135
  • 159
  • thanks, this did kind of solve the issue. it still did not work, and I tried this version a couple of times before, but then I figured I got the wrong password. Anyways, thanks for pointing out the correct approach so that I could focus on other things, rather than trying different combinations! – uglycode Oct 23 '17 at 17:17
  • When I used the above, I’m getting fs.readFileSync is not a function. – Len Oct 04 '18 at 12:22
  • Instead of using fs.readFileSync, is there an alternative? I am getting its not a function. The fs object is empty when I log it out – Huiting Jun 29 '19 at 04:24
  • There is so little documentation out there about using pfx files with requests. I'd give you a hundred upvotes if I could, thanks! – Graham May 03 '20 at 14:53
3

The request API in the other comment from Bertrand Martel is deprecated and therefore not secure, you can also use axios to achieve the same thing:

const fs = require('fs');
const axios = require('axios');
const https = require('https');

const response = await axios.request({
    url: *URL_HERE*,
    method: 'post',
    headers: {
        "content-type": "application/json",
    },
    data: JSON.stringify({
        *YOUR_DATA_HERE*
    }),
    httpsAgent: new https.Agent({
        passphrase: *PASSPHRASE_HERE*,
        pfx: fs.readFileSync(__dirname + '\\..\\certificates\\certificate.p12'),
    })
});
jakobinn
  • 1,832
  • 1
  • 20
  • 20