04-27-2023 10:36 AM
I am using the below script in preprocessing step in POSTMAN but it is throwing an error
code": 40103,
“message”: “Invalid signature in request credentials”,
“stat”: “FAIL”
“PRE PROCESSING SCRIPT”
function getAuthHeader(httpMethod, requestUrl, requestBody) { console.log(requestBody); //body data console.log(httpMethod); // http type: POST, GET, ETC
var CLIENT_KEY = ‘xxxxxxx’;
var SECRET_KEY = ‘xxxxxxx’;
//var AUTH_TYPE = ‘HMAC-SHA1’;
var moment = require(‘moment’)
//const moment= require(‘moment’);
/* Uncomment out lines below to use your test for getting correct formatted time and date */
var timestamp = moment().format(‘ddd, DD MMM YYYY HH:mm:ss ZZ’);
//var timestamp1 = moment().utcOffset(‘timestamp’);
//var timestamp1 = timestamp.toUTCString();
pm.environment.set(“timestampHeader”,timestamp);
//var timestamp = “Mon, 24 Apr 2023 16:38:18 -0600” ;
//pm.environment.set(“timestampHeader”,timestamp);
var hostname = “■■■■■■■■■■■■■■■■■■■■■■■■”;
var apicall = ‘/admin/v1/users’
var method = ‘POST’
var body = ‘username=xxxx’ //sample username
var requestData = timestamp +‘\n’+method+‘\n’+ hostname +‘\n’+ apicall +‘\n’+ body;
//requestData = requestData.normalize([‘NFC’]);
console.log(requestData);
var hmacDigest = CryptoJS.HmacSHA1(requestData, SECRET_KEY);
console.log(hmacDigest);
var prebase = CLIENT_KEY+“:”+hmacDigest;
console.log(prebase);
var baseComplete = btoa(prebase);
console.log(baseComplete);
var authHeader = "Basic "+baseComplete;
return authHeader;
}
postman.setEnvironmentVariable(‘hmacAuthHeader’, getAuthHeader(request[‘method’], request[‘url’], request[‘data’]));
Headers :
I have seen few similar posts on this script, but no one is clear on how they made it working.
So can someone help on what I am missing in the script and to convert time to UTC?
Solved! Go to Solution.
04-28-2023 06:42 PM
Hi @Apoorva_Anne ,
You might have already seen this lengthy thread regarding the topic: Preauth API failing but check and ping are good - #14 by testdemo_user
I will paste the pre-request script that I have been using successfully (taken from the above thread). You should only need to replace the ikey, skey and API hostname. Keep the Headers that you already have.
//Tested on Postman for Web Version 10.13.6
function getAuthHeader(httpMethod, requestUrl, requestBody) {
console.log(requestUrl); // Full URL
console.log(httpMethod); // http type: POST, GET, ETC
console.log(requestBody); //POST Body, currently not used
var IKEY = '<ikey>'; //Auth or Admin API IKEY
var SKEY = '<skey>'; //Auth or Admin API SKEY
var API_HOSTNAME = '<api-hostname>'; //Auth or Admin API Hostname
var AUTH_TYPE = 'HMAC-SHA1';
//Adds a ? at the end of the URL even if there aren't any parameters, makes it easier to find the end of the api_call
if (requestUrl.indexOf("?") == -1) {
requestUrl += "?";
}
var paramsStart = requestUrl.indexOf("?");
var hostname_length = API_HOSTNAME.length + 8; //api_hostname + https://
var api_call = requestUrl.slice(hostname_length, paramsStart); //remove hostname and params to get the api_call
console.log(api_call);
var params_unsorted = "";
var params_array = [];
//Create unsorted array of parameters from either URL or Body
//Assuming POST parameters are in the Body, GET paramters are in URL
//(technically it looks like POST can be in the URL as well)
if (Object.keys(requestBody).length !== 0) {
for (var parameter1 in requestBody) {
params_unsorted = parameter1 + "=" + requestBody[parameter1];
params_array.push(params_unsorted);
}
} else {
params_unsorted = requestUrl.substring(paramsStart+1);
params_array = params_unsorted.split("&");
}
console.log(params_array);
params_array.sort(); //lexicographically sort parameters by key
var encoded_params = "";
if (params_array[0] !== ""){ //check if there are any Params to encode and create the string from
var encoded_params_array = params_array.map(urlEncodeParams); //create URL-encoded array of key=value pairs from the sorted array
encoded_params = encoded_params_array.join("&"); //create string of parameters joined by &
}
console.log(encoded_params);
//The current time, formatted as RFC 2822. This must be the same string as the "Date" header (or X-Duo-Date header).
var moment = require('moment');
var timestamp = moment().format("ddd, DD MMM YYYY HH:mm:ss ZZ");
pm.environment.set("timestampHeader",timestamp);
//Then concatenate these components with (line feed) newlines
var requestData = timestamp+"\n"+httpMethod+"\n"+API_HOSTNAME+"\n"+api_call+"\n"+encoded_params;
console.log(requestData);
//compute the HMAC-SHA1 of this canonical representation, using your Duo application's secret key as the HMAC key
var hmacDigest = CryptoJS.HmacSHA1(requestData, SKEY);
console.log(hmacDigest);
//Use HTTP Basic Authentication for the request, using your integration key as the username and the HMAC-SHA1 signature as the password.
var prebase = IKEY+":"+ hmacDigest;
console.log(prebase);
//encodes a string in base-64
var baseComplete = btoa(prebase);
console.log(baseComplete);
var authHeader = "Basic "+ baseComplete;
return authHeader;
}
function urlEncodeParams(value, index, array) {
//split the Key and Value at the first "=", URL-encode the Value, and rejoin them with an "="
//If the separator in the split() is a regular expression that contains capturing parentheses (), matched results are included in the array
return value.split(/=(.+)/)[0] + "=" + encodeURIComponent(value.split(/=(.+)/)[1]);
}
pm.environment.set("hmacAuthHeader", getAuthHeader(request.method, request.url, request.data));
You can then perform the GET
or POST
to the endpoint of your choice (which initially appears to be https://■■■■■■■■■■■■■■■■■■■■■■■■■■■■/admin/v1/users
) in the request field:
Hope this helps!
04-28-2023 06:42 PM
Hi @Apoorva_Anne ,
You might have already seen this lengthy thread regarding the topic: Preauth API failing but check and ping are good - #14 by testdemo_user
I will paste the pre-request script that I have been using successfully (taken from the above thread). You should only need to replace the ikey, skey and API hostname. Keep the Headers that you already have.
//Tested on Postman for Web Version 10.13.6
function getAuthHeader(httpMethod, requestUrl, requestBody) {
console.log(requestUrl); // Full URL
console.log(httpMethod); // http type: POST, GET, ETC
console.log(requestBody); //POST Body, currently not used
var IKEY = '<ikey>'; //Auth or Admin API IKEY
var SKEY = '<skey>'; //Auth or Admin API SKEY
var API_HOSTNAME = '<api-hostname>'; //Auth or Admin API Hostname
var AUTH_TYPE = 'HMAC-SHA1';
//Adds a ? at the end of the URL even if there aren't any parameters, makes it easier to find the end of the api_call
if (requestUrl.indexOf("?") == -1) {
requestUrl += "?";
}
var paramsStart = requestUrl.indexOf("?");
var hostname_length = API_HOSTNAME.length + 8; //api_hostname + https://
var api_call = requestUrl.slice(hostname_length, paramsStart); //remove hostname and params to get the api_call
console.log(api_call);
var params_unsorted = "";
var params_array = [];
//Create unsorted array of parameters from either URL or Body
//Assuming POST parameters are in the Body, GET paramters are in URL
//(technically it looks like POST can be in the URL as well)
if (Object.keys(requestBody).length !== 0) {
for (var parameter1 in requestBody) {
params_unsorted = parameter1 + "=" + requestBody[parameter1];
params_array.push(params_unsorted);
}
} else {
params_unsorted = requestUrl.substring(paramsStart+1);
params_array = params_unsorted.split("&");
}
console.log(params_array);
params_array.sort(); //lexicographically sort parameters by key
var encoded_params = "";
if (params_array[0] !== ""){ //check if there are any Params to encode and create the string from
var encoded_params_array = params_array.map(urlEncodeParams); //create URL-encoded array of key=value pairs from the sorted array
encoded_params = encoded_params_array.join("&"); //create string of parameters joined by &
}
console.log(encoded_params);
//The current time, formatted as RFC 2822. This must be the same string as the "Date" header (or X-Duo-Date header).
var moment = require('moment');
var timestamp = moment().format("ddd, DD MMM YYYY HH:mm:ss ZZ");
pm.environment.set("timestampHeader",timestamp);
//Then concatenate these components with (line feed) newlines
var requestData = timestamp+"\n"+httpMethod+"\n"+API_HOSTNAME+"\n"+api_call+"\n"+encoded_params;
console.log(requestData);
//compute the HMAC-SHA1 of this canonical representation, using your Duo application's secret key as the HMAC key
var hmacDigest = CryptoJS.HmacSHA1(requestData, SKEY);
console.log(hmacDigest);
//Use HTTP Basic Authentication for the request, using your integration key as the username and the HMAC-SHA1 signature as the password.
var prebase = IKEY+":"+ hmacDigest;
console.log(prebase);
//encodes a string in base-64
var baseComplete = btoa(prebase);
console.log(baseComplete);
var authHeader = "Basic "+ baseComplete;
return authHeader;
}
function urlEncodeParams(value, index, array) {
//split the Key and Value at the first "=", URL-encode the Value, and rejoin them with an "="
//If the separator in the split() is a regular expression that contains capturing parentheses (), matched results are included in the array
return value.split(/=(.+)/)[0] + "=" + encodeURIComponent(value.split(/=(.+)/)[1]);
}
pm.environment.set("hmacAuthHeader", getAuthHeader(request.method, request.url, request.data));
You can then perform the GET
or POST
to the endpoint of your choice (which initially appears to be https://■■■■■■■■■■■■■■■■■■■■■■■■■■■■/admin/v1/users
) in the request field:
Hope this helps!
05-05-2023 12:42 PM
Hey thanks for the script, Now it worked for me in postman.
Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: