ADP's REST API requires that a SSL certificate and private key be sent with every request.
When I use the 'standard, Node.js HTTP(S) module:
require('dotenv').config()
const fs = require('fs')
const path = require('path')
const certificate_path = path.resolve('../credentials/certificate.pem')
const private_key_path = path.resolve('../credentials/private.key')
const options = {
hostname: 'api.adp.com',
path: '/hr/v2/workers/ABCDEFGHIJKLMNOP',
method: 'GET',
headers: {
'Accept': 'application/json;masked=false',
'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`
},
cert: fs.readFileSync(certificate_path, "utf8"),
key: fs.readFileSync(private_key_path, "utf8"),
};
require('https').get(options, res => {
let data = [];
res.on('data', chunk => {
data.push(chunk);
});
res.on('end', () => {
const workers = JSON.parse(Buffer.concat(data).toString());
for(worker of workers.workers) {
console.log(`Got worker with id: ${worker.associateOID}, name: ${worker.person.legalName.formattedName}`);
}
});
}).on('error', err => {
console.log('Error: ', err.message);
});
The request works as expected:
$ node ./standard.js
Got worker with id: ABCDEFGHIJKLMNOP, name: Last, First
However, when I use node-fetch:
require('dotenv').config()
const fs = require('fs')
const path = require('path')
const certificate_path = path.resolve('../credentials/certificate.pem')
const private_key_path = path.resolve('../credentials/private.key')
const url = 'https://accounts.adp.com/hr/v2/workers/ABCDEFGHIJKLMNOP'
const options = {
headers: {
'Accept': 'application/json;masked=false',
'Authorization': `Bearer ${process.env.ACCESS_TOKEN}`
},
agent: new require('https').Agent({
cert: fs.readFileSync(certificate_path, "utf8"),
key: fs.readFileSync(private_key_path, "utf8")
})
}
fetch(url,options)
.then((response) => response.json())
.then((body) => {
console.log(body);
});
I get an error:
$ node ./fetch.js
{
response: {
responseCode: 401,
methodCode: 'GET',
resourceUri: { href: '/hr/v2/workers/ABCDEFGHIJKLMNOP' },
serverRequestDateTime: '2023-03-30T14:25:23.351Z',
applicationCode: {
code: 401,
typeCode: 'error',
message: 'Request did not provide the required two-way TLS certificate'
},
client_ip_adddress: 'a.b.c.d',
'adp-correlationID': '61f76d29-04e1-48b8-be9d-acf459408b2b'
}
}
What am I missing in the second approach?
I don't see any import of node-fetch so I assume you're using the new native fetch added to Node18. The new global fetch does not (yet) support agent options.
See why is the agent option not available in node native fetch?