Invalid signature with telesign call REST API

The API sends a verification code via a phone call, which the user then enters into the website ... basically verifying that the phone number is valid.

But I am having trouble signing the request. No matter what I try, it returns "Invalid Signature"

API documentation: http://docs.telesign.com/rest/content/verify-call.html

Authentication documentation: http://docs.telesign.com/rest/content/rest-auth.html

Authentication examples: http://docs.telesign.com/rest/content/auth-examples.html

Code:

<cffunction name="encryptHmacSHA1" returntype="binary" access="public" output="false">
    <cfargument name="base64Key" type="string" required="true">
    <cfargument name="signMessage" type="string" required="true">
    <cfargument name="encoding" type="string" default="UTF-8">

    <cfset var messageBytes = JavaCast("string",arguments.signMessage).getBytes(arguments.encoding)>
    <cfset var keyBytes = binaryDecode(arguments.base64Key, "base64")>
    <cfset var key  = createObject("java","javax.crypto.spec.SecretKeySpec")>
    <cfset var mac  = createObject("java","javax.crypto.Mac")>
    <cfset key  = key.init(keyBytes,"HmacSHA1")>
    <cfset mac  = mac.getInstance(key.getAlgorithm())>
    <cfset mac.init(key)>
    <cfset mac.update(messageBytes)>

    <cfreturn mac.doFinal()>
</cffunction>


<cfscript>
    // PHONE NUMBER TO CALL
    phoneNumberToCall = "15554565555"; 

    // KEYS
    keys = structNew();
    keys.customerID = "D561FCF4-BA8D-4DFC-86D1-1A46DF47A308";
    keys.apiKey = "mDzGHsMOc2g/ivkuINEFVh6fn/v4kdjvlTvtgFVOShu7hVWXS0eV2nLSw1FXgEzDSuOjhlKLXvneiq+YFG1/Vg==";

    // DATES
    dates = structNew();
    dates.timeZoneInfo = GetTimeZoneInfo();
    dates.dateToUse = DateAdd("h",dates.timeZoneInfo.utcHourOffset,now());
    dates.signingDate = DateFormat(dates.dateToUse,"ddd, dd mmm yyyy") & " " & TimeFormat(dates.dateToUse,"HH:mm:ss") & " +0000";


    // HEADERS
    headers = [ 
           "POST",
           "application/x-www-form-urlencoded", 
           "#dates.signingDate#",
           "phone_number=#phoneNumberToCall#&ucid=OTHR", 
           "/v1/verify/call"
          ];

    headerText = arrayToList(headers, chr(10)) & chr(10);

    // CREATE SIGNATURE
    stringToSign = binaryEncode( encryptHmacSHA1(keys.apiKey, headerText), "base64");

    // AUTHORIZE HEADER
    Authorization = "TSA" & " " & keys.customerID & ":" & stringToSign;
</cfscript>

<cfhttp method="POST" url="https://rest.telesign.com/v1/verify/call" port="443" charset="UTF-8" result="verifyPhoneCall"> 
    <cfhttpparam type="header" name="authorization" value="#Authorization#">
    <cfhttpparam type="header" name="content-type" value="application/x-www-form-urlencoded">
    <cfhttpparam type="header" name="date" value="#dates.signingDate#">
    <cfhttpparam name="phone_number" value="#phoneNumberToCall#" type="formfield">
    <cfhttpparam name="ucid" value="OTHR" type="formfield">
</cfhttp>
<cfdump var="#verifyPhoneCall#"> 

      

Headers should be included in the signature with "new lines". And the docs also say they must be in the order the http tag sends them. I don't think I have the correct order ... or even how should I set the order in the cfhttp call.

Any help is appreciated. And yes, the keys are real. I will create new ones soon.

Thank,

Brian

+3


source to share


1 answer


Looking back at his documentation on Creating CanonicalizedPOSTVariables element , it mentions that the POST body must match the string used when constructing the signature (highlight)

... when you create the signature line, you must use the body of the POST request exactly as it is being delivered to the service.

By default, cfhttpparam

url encodes any value formField

. Since you do not encode these values ​​when creating the signature, the content provided by cfhttp does not match. Hence the error.

Disable automatic encoding for all form fields in signature:

   <cfhttpparam name="phone_number" 
         value="#phoneNumberToCall#"
         type="formfield"  
         encoded="false">

      

... or use type = "body" instead. Then you have complete control over the content of the message:



   <cfhttpparam type="body" 
       value="phone_number=15554565555&ucid=OTHR">

      

Update:

Also, get rid of the last newline, that is chr (10) in "headerText". Otherwise, your cfhttp content will still not match the signature. those. use this:

headerText = arrayToList(headers, chr(10));

      

.. instead of:

headerText = arrayToList(headers, chr(10)) & chr(10);

      

0


source







All Articles