| « PreviousNext » | |
![]() | Did this page help you? Yes | No | Tell us about it... |
You must standardize the format of your request to the same format AWS uses when it recalculates your signature. Formatting the request into an unambiguous, canonical format before signing it, ensures that you and AWS will calculate the same signature that you calculated for a given request. Non-standardized formatting can result in different HMAC signatures.
You create a canonical request by concatenating the following components:
Canonical request pseudocode
CanonicalRequest =HTTPRequestMethod+ '\n' +CanonicalURI+ '\n' +CanonicalQueryString+ '\n' +CanonicalHeaders+ '\n' +SignedHeaders+ '\n' + HexEncode(Hash(Payload))
In the previous example, the HexEncode function represents a function that
returns the base-16 encoding of its sole input value using lowercase characters. For
example, HexEncode("m") returns the value 6d rather than
6D. Each input byte must be represented as exactly two hexadecimal
characters.
To show you how to construct the canonical form of an HTTP or HTTPS request, let's use the following sample request:
Sample request
POST http://iam.amazonaws.com/ HTTP/1.1 host: iam.amazonaws.com Content-type: application/x-www-form-urlencoded; charset=utf-8 x-amz-date: 20110909T233600Z Action=ListUsers&Version=2010-05-08
The sample request is a POST request (method) that makes a ListUsers API
(action) call to AWS Identity and Access Management (host).
To create a canonical request, concatenate the following components from each step into a single string:
Start with the HTTP request method (GET, PUT, POST, etc.).
Add the CanonicalURI parameter. This is the URI-encoded version of the
absolute path component of the URI—everything from the HTTP host
header to the question mark character ('?') that begins the query string
parameters. Then add a newline character.
Normalize URI paths according to RFC 3986 by removing redundant and relative path components. Each path segment must be URI-encoded. If the absolute path is empty, use a forward slash (/).
Add the CanonicalQueryString parameter. If the request does not include a
query string, set the value of CanonicalQueryString to an empty
string.
To construct the canonical query string, complete the following steps:
URI encode each parameter name and value according to the following rules:
Do not URL-encode any of the unreserved characters that RFC 3986 defines: A-Z, a-z, 0-9, hyphen ( - ), underscore ( _ ), period ( . ), and tilde ( ~ ).
Percent-encode all other characters with %XY, where X and Y are hexadecimal characters (0-9 and uppercase A-F).
For example, the space character must be encoded as %20 (and not '+', as some encoding schemes do) and extended UTF-8 characters must be in the form %XY%ZA%BC.
Sort the encoded parameter names by character code (that is, in strict ASCII order). For example, a parameter name that begins with the uppercase letter F (ASCII code 70) precedes a parameter name that begins with a lowercase letter b (ASCII code 98).
Build the canonical query string by starting with the first parameter name in the sorted list.
For each parameter, append the URI-encoded parameter name, followed by the character '=' (ASCII code 61), followed by the URI-encoded parameter value.
Use an empty string for parameters that have no value.
Append the character '&' (ASCII code 38) after each parameter value except for the last value in the list.
In some cases, you might construct a request where all the authorization parameters are in the query string, such as pre-signed URLs for Amazon S3. In such cases, the canonical query string must include the algorithm, credential scope, date, and signed headers parameters, as shown in the following example:
Authorization parameters in a query string
Action=ListUsers& Version=2010-05-08& X-Amz-Algorithm=AWS4-HMAC-SHA256& X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20110909%2Fus-east-1%2Fiam%2Faws4_request& X-Amz-Date=20110909T233600Z& X-Amz-SignedHeaders=content-type%3Bhost%3Bx-amz-date
The previous example was formatted for human readability. The canonical query string must be one continuous line of text. For more information about the authorization parameters, see Task 2: Create a String to Sign for Signature Version 4.
Add the CanonicalHeaders parameter, which is a list of all the HTTP headers
for the request. You must include a valid host header. Any other required
headers are described by the service you're using.
Sample request: CanonicalHeaders
content-type:application/x-www-form-urlencoded; charset=utf-8\n host:iam.amazonaws.com\n x-amz-date:20110909T233600Z\n
To create a canonical headers list, convert all header names to lowercase and trim excess white space characters out of the header values. When you trim, remove leading spaces and trailing spaces, and convert sequential spaces in the value to a single space. However, do not remove extra spaces from any values that are inside quotation marks.
The following pseudocode describes how to construct the canonical list of headers:
CanonicalHeaders =CanonicalHeadersEntry0+CanonicalHeadersEntry1+ ... +CanonicalHeadersEntryNCanonicalHeadersEntry = LOWERCASE(HeaderName) + ':' + TRIMALL(HeaderValue) + '\n'
LOWERCASE represents a function that converts all characters to lowercase.
TRIMALL represents a function that removes excess white
space before and after values and from inside non-quoted strings, per RFC 2616 Section
4.2.
Build the canonical headers list by iterating through the collection of header names, sorted by lowercase character code. Construct each header by using the following rules:
Append the lowercase header name followed by a colon.
Append a comma-separated list of values for that header. If there are duplicate headers, the values are comma-separated. Do not sort the values in headers that have multiple values.
Append a newline ('\n').
To show an additional example, the following two samples compare a more complex set of headers with their canonical form:
Original headers
host:iam.amazonaws.com\n Content-type:application/x-www-form-urlencoded; charset=utf-8\n My-header1: a b c \n x-amz-date:20120228T030031Z\n My-Header2: "a b c"\n
Canonical form
content-type:application/x-www-form-urlencoded; charset=utf-8\n host:iam.amazonaws.com\n my-header1:a b c\n my-header2:"a b c"\n x-amz-date:20120228T024136Z\n
In the canonical form, the following changes were done:
The header names have been converted to lowercase characters.
The headers have been sorted by character code.
Removed extra spaces for the value of my-header1 because it's not in
quotation marks.
No extra spaces were removed for the value of my-header2 because it's in
quotation marks.
Removed leading spaces for the my-header1 and my-header2
values.
Add the SignedHeaders parameter, which is the list of HTTP headers that you
included in the canonical headers. You must include a list of signed headers
because extra headers are often added to the request by the transport
layers. The list of signed headers enables AWS to determine which headers
are part of your original request.
The host header must be included as a signed header. If you include a date
or x-amz-date header, you must also include that header in the
list of signed headers.
To create the signed headers list, convert all header names to lowercase,
sort them by character code, and use a semicolon to separate the header
names. The following pseudocode describes how to construct a list of signed
headers. LOWERCASE represents a function that converts all
characters to lowercase.
SignedHeaders = LOWERCASE(HeaderName0) + ';' + LOWERCASE(HeaderName1) + ... + LOWERCASE(HeaderNameN)
Build the signed headers list by iterating through the collection of header names, sorted by lowercase character code.
For each header name except the last, append a semicolon (';') to the header name to separate it from the following header name.
Add the payload, which you derive from the body of the HTTP or HTTPS request.
To create the payload, use a signing algorithm to encode the body of the HTTP or HTTPS request. If the payload is empty, use the empty string as the input to the hash function. The resulting payload is the lowercase hex (base-16) encoded digest.
The following example uses SHA256 to hash the payload:
Note
When you create the string to sign (Task 2: Create a String to Sign for
Signature Version 4), you will specify the
signing algorithm that you used to hash the payload. For example, if you
used SHA256, you will specify AWS4-HMAC-SHA256 as the
signing algorithm.
To construct the final canonical request, combine all the components from each step as a single string. If you follow the canonical request pseudocode, the resulting canonical request is shown in the following example:
Sample request: Canonical form
POST / content-type:application/x-www-form-urlencoded; charset=utf-8 host:iam.amazonaws.com x-amz-date:20110909T233600Z content-type;host;x-amz-date b6359072c78d70ebee1e81adcbab4f01bf2c23245fa365ef83fe8f1f955085e2
Hash the canonical request by using the same algorithm from that you used to hash the payload.
The hashed canonical request is lowercase base-16 encoded. The following sample example uses SHA256 to hash the canonical request:
Sample request: Hashed canonical request
3511de7e95d28ecd39e9513b642aee07e54f4941150d8df8bf94b328ef7e55e2
You include the hashed canonical request as part of the string to sign in Task 2: Create a String to Sign for Signature Version 4.