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
Mega 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!