Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Duo Authentication Header

danielmenter
Tera Expert

Hi all like numerous others I am trying to setup some automation directly from ServiceNow to our duo client. However I am unable to get authorized.

https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB1641630

https://duo.com/docs/adminapi#authentication


I have created the following code to test the example from the duo api documentation.
I am getting a similar result to the example but neither GlideDigest or the function from the kb article produce a matching result.

var duotenant = "xxxxxxxx";
var resourceMethod = "POST";
var resourcePath = "admin/v1/users";
var parameters = "realname=First%20Last&username=root";
var date = "Tue, 21 Aug 2012 17:29:18 -0000";
var example = "RElXSjhYNkFFWU9SNU9NQzZUUTE6YzFlZjQzNzY3YzNlYjNiMzI1OGRiZGRjYTZmOGQwOTQxZTA4NWI5Mg==";
var authHeader = generateAuthHeader(date, resourceMethod, duotenant, resourcePath, parameters);
gs.info("\nExample "+ example + "\nGenerated " + authHeader);

function generateAuthHeader(date, resourceMethod, duotenant, resourcePath, parameters) {
    var secretKey = "Zh5eGmUq9zpfQnyUIu5OL9iWoMMv5ZNmk3zLJ4Ep";
    var integrationKey = "DIWJ8X6AEYOR5OMC6TQ1";

    //create canonical representation
    var canonicalAuthHeader = date + "\n";
    canonicalAuthHeader += resourceMethod.toUpperCase() + "\n";
    canonicalAuthHeader += "api-" + duotenant.toLowerCase() + ".duosecurity.com" + "\n";
    canonicalAuthHeader += resourcePath + "\n";
    canonicalAuthHeader += parameters;

    //compute the HMAC-SHA1 of this canonical representation
    var mac = new GlideCertificateEncryption;
    var key = GlideStringUtil.base64Encode(secretKey);
    var hmackey = mac.generateMac(key, "HmacSHA1", canonicalAuthHeader);

    

    //Using GlideDigest with getSHA1Hex() method to get hexadecimal ASCII of the hash value calculated using "GlideCertificateEncryption"
    var digest = new GlideDigest();
    //var password = digest.getSHA1Hex(hamckey).toLowerCase();
 var password = toHexString(hmackey);

    var signature = GlideStringUtil.base64Encode(integrationKey + ":" + password);

    function toHexString(credentials) {
        // Decode base64 to binary
        var binaryData = GlideStringUtil.base64DecodeAsBytes(credentials);
        // Convert binary to hexadecimal
        var hex = '';
        for (var i = 0; i < binaryData.length; i++) {
            var byteValue = binaryData[i];
            var hexString = ('0' + (byteValue & 0xFF).toString(16)).slice(-2); // Convert byte to hexadecimal
            hex += hexString;
        }
        return hex;
    }

    return signature;
}


Using the ToHexString from the KB
Example
RElXSjhYNkFFWU9SNU9NQzZUUTE6YzFlZjQzNzY3YzNlYjNiMzI1OGRiZGRjYTZmOGQwOTQxZTA4NWI5Mg==
Generated
RElXSjhYNkFFWU9SNU9NQzZUUTE6ODcyMmYyMjRhNDBhNWJlZGM3YzNmODQxYTE3MzMwOTVjZTU4Mzg4YQ==

Using the GlideDigest
Example
RElXSjhYNkFFWU9SNU9NQzZUUTE6YzFlZjQzNzY3YzNlYjNiMzI1OGRiZGRjYTZmOGQwOTQxZTA4NWI5Mg==
Generated
RElXSjhYNkFFWU9SNU9NQzZUUTE6ODgwYjU2MjJhODBiMmNlZTllYWU3N2UwMWI4YzEzN2Q0ZWIyYmUyNw==


1 ACCEPTED SOLUTION

danielmenter
Tera Expert

Was able to get it working.

var duotenant = "xxxxxxxx";
var resourceMethod = "POST";
var resourcePath = "/admin/v1/users";
var parameters = "realname=First%20Last&username=root";
var date = "Tue, 21 Aug 2012 17:29:18 -0000";
var example = "RElXSjhYNkFFWU9SNU9NQzZUUTE6YzFlZjQzNzY3YzNlYjNiMzI1OGRiZGRjYTZmOGQwOTQxZTA4NWI5Mg==";
var authSignature = generateAuthSignature(date, resourceMethod, duotenant, resourcePath, parameters);
gs.info("\nExample "+ example + "\nNew Sig " + authSignature);

function generateAuthSignature(date, resourceMethod, duotenant, resourcePath, parameters) {
    var secretKey = "Zh5eGmUq9zpfQnyUIu5OL9iWoMMv5ZNmk3zLJ4Ep";
    var integrationKey = "DIWJ8X6AEYOR5OMC6TQ1";

    //create canonical representation
    var canonicalAuthHeader = date + "\n";
    canonicalAuthHeader += resourceMethod.toUpperCase() + "\n";
    canonicalAuthHeader += "api-" + duotenant.toLowerCase() + ".duosecurity.com" + "\n";
    canonicalAuthHeader += resourcePath + "\n";
    canonicalAuthHeader += parameters;

    //compute the HMAC-SHA1 of this canonical representation
    var mac = new GlideCertificateEncryption;
    var key = GlideStringUtil.base64Encode(secretKey);
    var hmackey = mac.generateMac(key, "HmacSHA1", canonicalAuthHeader);

    //Send this signature as hexadecimal ASCII (i.e. not raw binary data).
    var password = toHexString(hmackey);

    //integration key as the username and the HMAC-SHA1 signature as the password
    var signature = GlideStringUtil.base64Encode(integrationKey + ":" + password);
    return signature;

    function toHexString(credentials) {
        // Decode base64 to binary
        var binaryData = GlideStringUtil.base64DecodeAsBytes(credentials);
        // Convert binary to hexadecimal
        var hex = '';
        for (var i = 0; i < binaryData.length; i++) {
            var byteValue = binaryData[i];
            var hexString = ('0' + (byteValue & 0xFF).toString(16)).slice(-2); // Convert byte to hexadecimal
            hex += hexString;
        }
        return hex;
    }
}

View solution in original post

9 REPLIES 9

palanikumar
Giga Sage
Giga Sage

Try this in PostMan and see whether it is working fine. 

Thank you,
Palani

Works fine in postman.

danielmenter_0-1749575318390.png

 

danielmenter
Tera Expert

Was able to get it working.

var duotenant = "xxxxxxxx";
var resourceMethod = "POST";
var resourcePath = "/admin/v1/users";
var parameters = "realname=First%20Last&username=root";
var date = "Tue, 21 Aug 2012 17:29:18 -0000";
var example = "RElXSjhYNkFFWU9SNU9NQzZUUTE6YzFlZjQzNzY3YzNlYjNiMzI1OGRiZGRjYTZmOGQwOTQxZTA4NWI5Mg==";
var authSignature = generateAuthSignature(date, resourceMethod, duotenant, resourcePath, parameters);
gs.info("\nExample "+ example + "\nNew Sig " + authSignature);

function generateAuthSignature(date, resourceMethod, duotenant, resourcePath, parameters) {
    var secretKey = "Zh5eGmUq9zpfQnyUIu5OL9iWoMMv5ZNmk3zLJ4Ep";
    var integrationKey = "DIWJ8X6AEYOR5OMC6TQ1";

    //create canonical representation
    var canonicalAuthHeader = date + "\n";
    canonicalAuthHeader += resourceMethod.toUpperCase() + "\n";
    canonicalAuthHeader += "api-" + duotenant.toLowerCase() + ".duosecurity.com" + "\n";
    canonicalAuthHeader += resourcePath + "\n";
    canonicalAuthHeader += parameters;

    //compute the HMAC-SHA1 of this canonical representation
    var mac = new GlideCertificateEncryption;
    var key = GlideStringUtil.base64Encode(secretKey);
    var hmackey = mac.generateMac(key, "HmacSHA1", canonicalAuthHeader);

    //Send this signature as hexadecimal ASCII (i.e. not raw binary data).
    var password = toHexString(hmackey);

    //integration key as the username and the HMAC-SHA1 signature as the password
    var signature = GlideStringUtil.base64Encode(integrationKey + ":" + password);
    return signature;

    function toHexString(credentials) {
        // Decode base64 to binary
        var binaryData = GlideStringUtil.base64DecodeAsBytes(credentials);
        // Convert binary to hexadecimal
        var hex = '';
        for (var i = 0; i < binaryData.length; i++) {
            var byteValue = binaryData[i];
            var hexString = ('0' + (byteValue & 0xFF).toString(16)).slice(-2); // Convert byte to hexadecimal
            hex += hexString;
        }
        return hex;
    }
}

Hi Daniel,

 

Could you please help me to test /auth/v2/auth in Postman.

  1. Do I need to add Params for username, device, factor etc?
    JLeong_0-1755141192161.png

     

  2.  For Authorization tab, what should I put as the password? I used Basic Auth.

  3. For the Header, I have the following, are these correct?
    JLeong_1-1755141286131.png

     

  4. Do I need to specify the body?

 

Thank you in advance!