question

Upvotes
Accepted
3 1 1 3

World Check One : 401 Unauthorized Error through Node.js code on POST request only

Hi All, I am trying to make POST requests to WorldCheck One APIs using Node.js code provided in the documentation. I am getting correct response from GET requests but when I try to make POST request , I get unauthorized 401 error . The same POST request gets 200 success when called through postman.


For Auth I am using code provided in documentation. I just changed the method for calculating Content-Length. apiKey , apisecret and GroupID are not given for security.


const axios = require('axios');
const crypto = require('crypto');

/**
 * Generates object that contains authorization headers (Date, Authorization, Content-Type, Content-Length).
 *
 * @param apiKey User's API key.
 * @param apiSecret User's API secret key.
 * @param method HTTP method of a request (e.g. 'get', 'options', 'head', 'post', 'put', 'patch', or 'delete').
 * @param url Full form URL (e.g. 'https://www.example.com/resources').
 * @param contentType (optional) Content type header value (e.g. 'application/json').
 * @param payload (optional) Object representing content.
 * @returns {
  {Authorization: string, Date: string}} (optional) Content-Type: string, (optional) Content-Length: number.
 */

var apikey = '*************';
var apiSecret = '******************';
var method = 'POST';
var url =  'https://api-worldcheck.refinitiv.com/v2/cases/screeningRequest'
var contentType = 'application/json';
var payload = {
"groupId": "**********",    // This is the correct group ID for my PILOT environment
"entityType": "INDIVIDUAL",
"caseId": "MNKJIOLKLM",
"providerTypes": [
  "WATCHLIST"
],
"caseScreeningState": {
  "WATCHLIST": "INITIAL"
},
"name": "John Ahmed",
"nameTransposition": false,
"secondaryFields": [],
"customFields": []
  }

function generateAuthorizationHeaders(apiKey, apiSecret, method, url, contentType, payload) {
validatePayload(contentType, payload);

let date = getDate();
let authorization = generateAuthorizationHeader(apiKey, apiSecret, method, url, contentType, payload, date);
let authorizationHeaders = {
'Date': date,
'Authorization': authorization
}

if (!!payload && Object.keys(payload).length > 0) {
        let payloadString = JSON.stringify(payload);
        authorizationHeaders["Content-Type"] = contentType; 
        authorizationHeaders["Content-Length"] = Buffer.byteLength(payloadString);    // As a json obj, payloadString.length was returning undefined. 
    }

return authorizationHeaders;
}

function validatePayload(contentType, payload) {
if (contentType != null && !contentType.toString().startsWith("application/json")) {
throw new Error("Unsupported content type: " + contentType);
}
if (payload == null && contentType != null) {
throw new Error("The request payload (body) has not been provided");
}
if (contentType == null && payload != null) {
throw new Error("The content type of request payload (body) has not been provided");
}
}

function getDate() {
return new Date().toUTCString();
}

function generateAuthorizationHeader(apiKey, apiSecret, method, url, contentType, payload, date) {
let httpMethod = method.toLowerCase();
let dataToSign = createDataToSign(httpMethod, url, contentType, payload, date);
let signature = generateHmacBase(dataToSign, apiSecret);

return getAuthHeader(signature, apiKey, payload);
}

function createDataToSign(method, url, contentType, payload, date) {
let parsedUrl = new URL(url);
let dataToSign =
"(request-target): " + method + " " + parsedUrl.pathname + "\nhost: " + parsedUrl.host + "\ndate: " + date;
if (!!payload) {
dataToSign += "\ncontent-type: " + contentType + "\n" + "content-length: " + payload.length + "\n" + payload;
}

return dataToSign;
}

function generateHmacBase(dataToSign, apiSecret) {
return crypto.createHmac('sha256', apiSecret).update(dataToSign).digest('base64');
}

function getAuthHeader(signature, apiKey, payload) {
let headers = !!payload ?  "(request-target) host date content-type content-length"
:  "(request-target) host date"


return "Signature keyId=\"" + apiKey +
   "\",algorithm=\"hmac-sha256\",headers=\"" + headers +
   "\",signature=\"" + signature + "\"";
}

exports.generateAuthorizationHeaders = generateAuthorizationHeaders;


// Make API call
function makeAPICall(apiKey, apiSecret, method, url, contentType, payload) {
    const authorizationHeaders = generateAuthorizationHeaders(apiKey, apiSecret, method, url, contentType, payload);

console.log(authorizationHeaders)
//console.log({data:payload})

    let config = {
method: method,
url: url,
headers: authorizationHeaders,
data : payload
  };
  
  axios.request(config)
  .then((response) => {
console.log(JSON.stringify(response.data));
  })
  .catch((error) => {
console.log(error);
  });
}

// Example usage
makeAPICall(apikey, apiSecret, method, url, contentType,payload);





#technology#productauthenticationworldcheck-one-api
icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

1 Answer

· Write an Answer
Upvote
Accepted
618 2 0 2

Hi @talha.k ,


Thank you for reaching out.

Please note that I have shared with you in a separate thread a node.js sample code which allows to make a synchronous POST call with the following url; https://api-worldcheck.refinitiv.com/v2/cases/screeningRequest


Best regards,


Virgill

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.