Duo API Integration: 401 Error Due to Invalid Signature - Correct Method for Generating HMAC-SHA1
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎08-27-2024 03:34 AM
Hi all,
I am encountering an issue with authenticating the Duo server when making a REST call to one of the Duo API endpoints from ServiceNow. I have created a UI action (a button DUO PUSH on the incident form) and written a ServiceNow JavaScript for the REST call. The integration uses Basic Authentication, and the Duo API documentation specifies that the client secret key should be encrypted using HMAC-SHA1.
Here is the relevant part of my code:
function sendPush() {
try {
//getting the caller id
var user_id = current.caller_id.user_name;
// Using the below code to get the date as mentioned in the cisco duo account api documentation.
//Example Date formate :Tue, 09 Aug 2024 17:29:18 -0000
var gdt = new GlideDate();
var duo_date = gdt.getByFormat("EEE, dd MMM YYYY HH:mm:ss ZZ");
var method = "GET"; // HTTP Method type.
var host = "api-axxxxxx.duosecurity.com"; //Host end point
var path = "/auth/v2/check"; //to verify that the Auth API integration and secret keys are valid, and that the signature is being generated properly.
var param = ""; // passing empty parameters. As per the Duo documentation if are not passing any parameters, and empty value should be provided.
//concatenate these components with (line feed) newlines.
var data = duo_date + '\n' + method + '\n' + host + '\n' + path;
gs.log("BS: Data " + data);
//Using "GlideCertificateEncryption" to generate HMAC-SHA1.
var mac = new GlideCertificateEncryption();
var skey = "Secret key shared by the client"; //Duo secret key
key = GlideStringUtil.base64Encode(skey);
var hash = mac.generateMac(key, "HmacSHA1", data);
gs.log("BS: has " + hash);
//Using GlideDigest with getSHA1Hex() method to get hexadecimal ASCII of the hash value calculated using "GlideCertificateEncryption"
var digest = new GlideDigest();
var password = digest.getSHA1Hex(hash).toLowerCase();
gs.log("BS: Hmach pass " + password);
//Converting ikey & Hmac password to base64 encoded
var ikey = "Intgertaion key shared by the client"; //Duo integration key
var basic_auth = ikey + ":" + password;
var base64_basic_auth = GlideStringUtil.base64Encode(basic_auth);
gs.log("BS: Base64 encoded ikey & hmac password " + base64_basic_auth);
//Endpoint of the REST API call.
var request = new sn_ws.RESTMessageV2();
var endpoint = "https://api-a5025657.duosecurity.com/auth/v2/check";
gs.log("BS: endpoint " + endpoint);
request.setEndpoint(endpoint);
//we need to pass the Authorization Header manually
var authorization = "Basic " + base64_basic_auth;
//Headers for the REST API call to integrate with the cisco duo.
request.setRequestHeader('Authorization', authorization);
request.setRequestHeader("Date", duo_date);
request.setHttpMethod('GET');
request.setRequestHeader('Content-Length', '0');
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
var response = request.execute();
var responseBody = response.getBody();
gs.log("BS: response body " + responseBody);
var httpStatus = response.getStatusCode();
gs.log("BS: httpstatus " + httpStatus);
var duoData = JSON.parse(responseBody);
if (duoData.result == 'allow') {
gs.addInfoMessage('The DUO push was accepted by the user.');
action.setRedirectURL(current);
}
if (duoData.result == 'deny') {
gs.addErrorMessage('The DUO push was denied by the user.');
action.setRedirectURL(current);
}
if (duoData.result == 'user-not-valid') {
gs.addErrorMessage('The user is not active in DUO or has no enrolled devices...');
action.setRedirectURL(current);
}
gs.info('DUO: ' + responseBody);
} catch (ex) {
var message = ex.message;
}
}
sendPush();
However, despite following the Duo API documentation, I am receiving a 401 error with the message:
{
"code": 40103,
"message": "Invalid signature in request credentials",
"stat": "FAIL"
}
Could you please assist in troubleshooting this issue? Specifically, I need guidance on the following:
Verification of HMAC-SHA1 Implementation: Is the method I’m using to generate the HMAC-SHA1 hash correct? Should the Secret key be encoded or processed in a different manner?
Correct Usage of GlideDigest: Are there any specific configurations or adjustments needed for the GlideDigest class to ensure proper HMAC-SHA1 hash generation?
For your reference, you can find the Duo API documentation on how to encrypt the client secret key using HMAC-SHA1 at the following link: https://duo.com/docs/authapi#api-details . To locate the relevant encryption steps, please navigate to API Details > Authentication.
Your assistance in resolving this issue would be greatly appreciated.
Thank you.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-16-2025 07:44 AM
Did you ever figure this one out? I am facing the same issue.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎06-18-2025 01:09 PM
I was able to figure out a solution
https://www.servicenow.com/community/developer-forum/duo-authentication-header/m-p/3285790#M1207942