Salesforce to Amazon Integration Using Signature Version 4: Part 1
If you are using Salesforce and are in need to store large sets of data, you may want to consider Amazon’s cost-effective storage as an alternative. Amazon provides access to its broad spectrum of AWS services by leveraging different versions of a signature such as version 1, version 2 and version 4.
What’s in a Signature?
Moving away from the bookish definitions, a signature is simply a computed alpha numeric value of a certain length that acts as a mechanism to verify the identity of the requester and protect the data in transit, in a service based communication model.
Amazon Signature version 4 is the protocol for authenticating inbound API requests to Amazon Web Services. It is considerably more secured than its version 2 variant and is supported in all geographical regions. In fact, any new regions after January 30, 2014 will only support Signature Version 4. In this two-post series, I will elucidate how to integrate Amazon with Salesforce by generating a signed request using Signature Version 4. While the first part would primarily deal with the creation of a canonical request, the second post will detail the calculation of a signature and creation of a signed request and conclude the integration process.
To sign a request using signature version 4, we need to calculate a signature that’s based on a combination of information in the request (For example, AWS service, region, action, time stamp, mode, access key and secret key). After calculating the signature, we need to add it to the request as a parameter, either in the header of the request or as a query-string parameter. Integrating Amazon to Salesforce using Signature Version 4 is essentially a 2-step process:
- Calculating a Signature
- Creating a Canonical Request
- Creating a String to Sign
- Calculating the Signature
- Creating a Signed Request
A. Calculating a Signature
Step 1: Creating a Canonical Request
The first step for calculating a Signature is to create a Canonical request. You need to arrange the content of your request into a standard canonical form and then create a Hash (digest) of the canonical request, add it to the canonical request and then create a digest of the updated canonical request. This is illustrated in the code snippet given below.
- HTTPMethod is our request mode (GET, POST)
- CanonicalizedResourcepath is the URI, i.e. everything in the URL from the HTTP host to the question mark character (“?”) that begins the query string parameters (if any). For this, we simply encode our endpoint using EncodingUtil.urlEncode method.
- Query parameters contain algorithm used, credentials, date and sign headers. All these query parameters are canonicalized using the function given below and are then used in forming a canonical request.
- HeaderNames will include the Names of header like host, date and content-type(if any).To create the signed headers list, you need to convert all header names to lowercase, sort them by character code, and then use a semicolon to separate the header names. Canonical HeaderNames will be calculated as shown below:
- Headers will include the Header name along with their values for request. You need to follow the same procedure for creating canonicalized headers that you used for creating canonicalizedHeaderNames. The function shown below gives an idea about how it is achieved:
- Finally using a hash (digest) function like SHA256, you need to create a hashed value from the payload in the body of the HTTP or HTTPS request. If the payload is empty, use the empty string as the input to the hash function. A typical hash function is as shown below.
Once you have completed all these steps, your canonical request will look like:
In my next post, I will take you through the process of creation of a string to sign, and the process to calculate the signature and finally, the creation of a signed request. So be ready with your canonical request!