ServiceNow Duo Integration

Praful_1968
Tera Contributor

Hello,

We're encountering an issue with integrating Cisco Duo with ServiceNow. Our goal is to authenticate with the Cisco Duo account API using the HMAC-SHA1 algorithm and retrieve account information.

We have successfully executed the API call using Postman, but when attempting the same authentication process within ServiceNow, we're encountering errors. 

 

Endpoint of Cisco Duo Account API

HTTP Method : POST (As per cisco duo account api documentation to retrieve accounts)

https://api-xxxxxxxx.duosecurity.com/accounts/v1/account/list 

 

Authentication steps followed :

1. Created the canonical representation as per the Cisco Duo account API documentation as below:

 

Tue, 12 Feb 2024 17:29:18 +0000

POST

api-xxxxxxxx.duosecurity.com

/accounts/v1/account/list

 

 2. Calculated the signature value using the secret key and HMAC-SHA1 algorithm.

3. Used the generated HMAC value as the password and the Cisco Duo account API Integration key as the username for basic authentication.

 

HMAC-SHA1 Generation Code in Postman:

let pc = require('postman-collection');
let cryptoJS = require('crypto-js');
let moment = require('moment');
let DATE = (moment().format("ddd, DD MMM YYYY HH:mm:ss ZZ"));
pm.environment.set("duo-DATE"DATE)
let METHOD = request.method;
let URL_OBJECT = new pc.Url(request.url);
//HOST is retrieved from the environment variable itself, since parsing the hostname using
//postman-collection's URL object will just give you the variable name.
let HOST = pm.environment.get("duo-API-HOST")
let PATH = URL_OBJECT.getPath();
//let QUERY = URL_OBJECT.getQueryString();
let QUERY = "";
let HMAC_STRING = DATE + "\n"
                + METHOD + "\n"
                + HOST + "\n"
                + PATH + "\n"
                + QUERY               
let HMACd = cryptoJS.HmacSHA1(HMAC_STRING, pm.environment.get("admin-skey")).toString();
pm.environment.set("duo-admin-HMAC"HMACd)
 
With the above code, I got a successful response in Postman.
 
I tried to do the same authentication in ServiceNow. We used the following code, but with that, we are getting the below error:
 
Error details:
Code: 40103
Message: "Invalid signature in request credentials"
Stat: "FAIL"
Response Error Msg: "Method failed: (/accounts/v1/account/list) with code: 401 - Invalid username/password combo"
 

Sample ServiceNow Script:

var ikey = "xxxxxxxxxxxxxxxxx"//Cisco Duo Integration Key
var skey= "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"// Cisco Duo Secret Key
var host = "api-xxxxxxxx.duosecurity.com";  // Cisco Duo Host

 

// Using the below code to get the date as mentioned in the cisco duo account api documentation.
//Tue, 21 Aug 2012 17:29:18 -0000

 

var gdt = new GlideDate();
var duo_date = gdt.getByFormat("EEE, dd MMM YYYY HH:mm:ss ZZ");
var method = "POST"//POST method is used to retrieve the accounts from the Cisco Duo
var path = "/accounts/v1/account/list"// Path for accounts.
var param = ""//As we are not passing any parameters for this keeping blank line

 

//concatenate these components with (line feed) newlines.
var data = duo_date+'\n'+method+'\n'+host+'\n'+path+'\n'+param;

 

//Using "GlideCertificateEncryption" to generate HMAC-SHA1.
var mac = new GlideCertificateEncryption;                          
key = GlideStringUtil.base64Encode(skey);
var hash = mac.generateMac(key, "HmacSHA1", data);

 

//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();

 

//Endpoint of the REST API call.

 

var request = new sn_ws.RESTMessageV2();
request.setEndpoint(endpoint);        
request.setHttpMethod('POST');
request.setBasicAuth(ikey,password);
request.setRequestHeader('Content-Length','0');
request.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
request.setRequestHeader("X-Duo-Date",duo_date);
//Above are the required Headers for the REST API call to integrate with the cisco duo.

 

var response = request.execute();

 

gs.info("Response body: "+response.getBody());
gs.info("Response Error Code: "+response.getErrorCode());
gs.info("Response Error Msg: "+response.getErrorMessage());
 
Can anyone help me with this authentication.
 
 
4 REPLIES 4

subbarayudu043
Tera Contributor

Hi,

Try with the below API 

getSHA1Base64(String source) 

 from https://developer.servicenow.com/dev.do#!/reference/api/washingtondc/server/no-namespace/c_GlideDige...

 

Scott_Robinson
Tera Contributor

@Praful_1968 - Were you ever able to figure this out. I am also working through this and am having similar issues. 

danielmenter
Tera Expert

danielmenter
Tera Expert