Validating a call signature

Eloqua signs all outgoing calls with OAuth 1.0a so the receiving system, in this case your app, can validate that the call was sent by Eloqua. As an app provider, it's your responsibility to ensure the validity of all inbound calls. Validation should be performed on every inbound call your app receives with OAuth parameters.

When your app receives a call from Eloqua, there are certain steps that must be taken to validate it. To illustrate these steps, let's say a POST request is received by your app from this URL:


https://example.com/eloqua/action/create?param1=value1&param2=value2&oauth_consumer_key=test_client_id&oauth_nonce=1234567&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1427308921&oauth_version=1.0&oauth_signature=EYKturXzLWMliisf/K9ySFFtgNo=
			

To validate a call signature

  1. Select the oauth_consumer_key value and ensure it matches your app's Client Id found in your app's configuration under Settings > AppCloud Developer in your Eloqua instance. If this value does not match your app's Client Id the call is invalid and should be discarded.
  2. Select the oauth_timestamp value and check that it is no more than 5 minutes older than your current server time. The timestamp will be in UTC in UNIX format (the number of seconds since January 1, 1970 00:00:00 GMT). If this value is more than 5 minutes old the call is invalid and should be discarded.
  3. Select the oauth_nonce value and compare it to oauth_nonce values for calls with the same oauth_timestamp. If it matches any other oauth_nonce values from a call with the same oauth_timestamp, the request is invalid and should be discarded.
  4. Cache the oauth_nonce and the corresponding oauth_timestamp values for 5 minutes so you can check the nonce against future calls.
  5. Calculate the first chunk of the signature base string. The signature base string consists of three parts, separated by ampersands ("&"):

    • The HTTP method (GET, POST, PUT, DELETE, etc.)
    • The URL endpoint without query string parameters, percent-encoded
    • The query parameters, omitting the oauth_signature parameter, sorted alphabetically, percent-encoded

    Using the https://example.com... example (see above), the first chunk of the signature base string, the HTTP method, is: POST.

  6. Calculate the second chunk of the signature base string. The second chunk consists of the URL endpoint without query parameters.

    Important: You need to ensure the URL does not include the port number. For example: https://example.com and not https://example.com:443. Notably, Java EE's native HttpServletRequest.getRequestURL() function returns a URL including the protocol, server name, port number, and server path.

    Using the above example we get: https://example.com/eloqua/action/create.This URL endpoint then needs to be percent-encoded. Using the above example we get:

    
    https%3A%2F%2Fexample.com%2Feloqua%2Faction%2Fcreate
    					

    Important: You need to ensure this string is encoded with percent codes and uppercase letters. For example, https://example.com should encode to https%3A%2F%2Fexample.com and not https%3a%2f%2fexample.com. Case sensitivity is not important in regular HTTP transport, but it is important when hashing to generate a signature. Notably, .NET's native HttpUtility.UrlEncode() function encodes strings with lower-case percent codes -- these will need to adjusted manually by looping through the string and ensuring the two characters after every percentage sign ("%") are in uppercase.

  7. Calculate the third chunk of the signature base string. The third chunk consists of the call's query parameters. Make sure not to include the question mark between endpoint URL and query string and to remove the oauth_signature parameter. Using the above example we get:

    
    param1=value1&param2=value2&oauth_consumer_key=test_client_id&oauth_ nonce=1234567&oauth_signature_method=HMAC-SHA1&oauth_ timestamp=1427308921&oauth_version=1.0
    					

    Then sort the parameters alphabetically. Using the above example we get:

    
    oauth_consumer_key=test_client_id&oauth_nonce=1234567&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1427308921&oauth_version=1.0&param1=value1&param2=value2
    					

    Finally, percent-encode the above URL to get the third chunk of the signature base string. Using the above example we get:

    oauth_consumer_key%3Dtest_client_id%26oauth_nonce%3D1234567%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1427308921%26oauth_version%3D1.0%26param1%3Dvalue1%26param2%3Dvalue2
    					
  8. Complete the signature base string by using ampersands to concatenate the three signature base string chunks: HTTP method, URL endpoint and query parameters. Using the above example we get the final signature base sting:

    
    POST&https%3A%2F%2Fexample.com%2Feloqua%2Faction%2Fcreate&oauth_consumer_ key%3Dtest_client_id%26oauth_nonce%3D1234567%26oauth_signature_ method%3DHMAC-SHA1%26oauth_timestamp%3D1427308921%26oauth_ version%3D1.0%26param1%3Dvalue1%26param2%3Dvalue2
    					

    Note: There should be two and only two ampersands in the resultant string. Any ampersands in the query string should have been percent-encoded into %26 strings, and any equal signs in the query string should have been percent-encoded into %3D strings.

    This signature base string will be used as your hash Message in subsequent validation steps. The following steps require a SHA1 cryptographic hash function (HMAC-SHA1) to create a keyed-hash message authentication code (known as the Message). Most programming languages offer easy-to-use libraries which accept a Message and Key to create the SHA1 hash.

    Important: With Eloqua, the hash Message = the call's signature base string and the Key = your app's Client Secret with an appended ampersand.

  9. Create a hash Key by appending an ampersand to your app's Client Secret. Your app's Client Secret can be found in your app's configuration under Settings > AppCloud Developer in your Eloqua instance. In your real-world app the Client Secret will be a string consisting of 100 random characters. In our example however, we'll say the Client Secret is: test_client_secret. For the purposes of creating the authentication code, you must append an ampersand to your app's Client Secret, so in this example we get: test_client_secret&.

  10. Enter your appropriately formatted Message and Key values into a SHA1 hash compute function. If your SHA1 compute function takes the Message and Key as strings, then you can enter the Message and Key exactly as calculated in previous steps. However, if your SHA1 hash compute function requires byte arrays (as is the case with .NET), you'll need to ASCII-encode your Message and Key into valid byte arrays.

    Using the above example, the Message would encode from:

    
    POST&https%3A%2F%2Fexample.com%2Feloqua%2Faction%2Fcreate&oauth_consumer_ key%3Dtest_client_id%26oauth_nonce%3D1234567%26oauth_signature_ method%3DHMAC-SHA1%26oauth_timestamp%3D1427308921%26oauth_ version%3D1.0%26param1%3Dvalue1%26param2%3Dvalue2
    					

    To the following array:

    50-4F-53-54-26-68-74-74-70-73-25-33-41-25-32-46-25-32-46-65-78-61-6D-70-6C-65-2E-63-6F-6D-25-32-46-65-6C-6F-71-75-61-25-32-46-61-63-74-69-6F-6E-25-32-46-63-72-65-61-74-65-26-6F-61-75-74-68-5F-63-6F-6E-73-75-6D-65-72-5F-6B-65-79-25-33-44-74-65-73-74-5F-63-6C-69-65-6E-74-5F-69-64-25-32-36-6F-61-75-74-68-5F-6E-6F-6E-63-65-25-33-44-31-32-33-34-35-36-37-25-32-36-6F-61-75-74-68-5F-73-69-67-6E-61-74-75-72-65-5F-6D-65-74-68-6F-64-25-33-44-48-4D-41-43-2D-53-48-41-31-25-32-36-6F-61-75-74-68-5F-74-69-6D-65-73-74-61-6D-70-25-33-44-31-34-32-37-33-30-38-39-32-31-25-32-36-6F-61-75-74-68-5F-76-65-72-73-69-6F-6E-25-33-44-31-2E-30-25-32-36-70-61-72-61-6D-31-25-33-44-76-61-6C-75-65-31-25-32-36-70-61-72-61-6D-32-25-33-44-76-61-6C-75-65-32
    					

    Similarly, the Key (the Client Secret) would encode from:

    
    test_client_secret&
    					

    To the following array:

    
    74-65-73-74-5F-63-6C-69-65-6E-74-5F-73-65-63-72-65-74-26
    					
  11. Run the SHA1 hash compute function with the appropriate values. This will result in either a byte array or string. In the above example, the array would look like this:

    11-82-AD-BA-B5-F3-2D-63-25-8A-2B-1F-FC-AF-72-48-51-6D-80-DA
    					

    You then need to convert the byte array into a base 64 string, which will give you the same string a string-returning function would have returned:

    EYKturXzLWMliisf/K9ySFFtgNo=
    					
  12. Compare the string your hash function returns to the original oauth_signature parameter sent from Eloqua. If the values match, the call is valid and your app can use it freely. If the values do not match the request is invalid and should be discarded.