Signing and Authenticating REST Requests

Authentication is the process of proving your identity to the system. Identity is an important factor in access control decisions. Requests are allowed or denied in part based on the identity of the requester. For example, the right to create buckets is reserved for registered developers and (by default) the right to create objects in a bucket is reserved for the owner of the bucket in question. As a developer, you'll be making requests that invoke these privileges, so you'll need to prove your identity to the system by authenticating your requests. This section shows you how.

The Norsk API uses a HTTP scheme based on a keyed-HMAC (Hash Message Authentication Code) for authentication. To authenticate a request, you first concatenate selected elements of the request to form a string. You then use your secret access key to calculate the HMAC of that string. Informally, we call this process "signing the request," and we call the output of the HMAC algorithm the signature, because it simulates the security properties of a real signature. Finally, you add this signature as a parameter of the request by using the syntax described in this section.

When the system receives an authenticated request, it fetches the secret access key that you claim to have and uses it in the same way to compute a signature for the message it received. It then compares the signature it calculated against the signature presented by the requester. If the two signatures match, the system concludes that the requester must have access to the secret access key and therefore acts with the authority of the principal to whom the key was issued. If the two signatures do not match, the request is dropped and the system responds with an error message.

Example Authenticated Request

GET /shipment/123/label HTTP/1.1
Date: Mon, 26 Mar 2007 19:37:58 +0000
Authorization: MISCACCOUNTEXAMPLE:vHhzsjuRLTLTAamvWFsSeI9Mltc=

The Authentication Header

The Norsk API uses the standard HTTP Authorization header to pass authentication information. (The name of the standard header is unfortunate because it carries authentication information, not authorization.) Under the authentication scheme, the Authorization header has the following form:

Authorization: NorskAccessKeyId:Signature

Developers are issued a access key ID and secret access key when they register. For request authentication, the NorskAccessKeyId element identifies the access key ID that was used to compute the signature and, indirectly, the developer making the request.

The Signature element is the RFC 2104 HMAC-SHA1 of selected elements from the request, and so the Signature part of the Authorization header will vary from request to request. If the request signature calculated by the system matches the Signature included with the request, the requester will have demonstrated possession of the AWS secret access key. The request will then be processed under the identity, and with the authority, of the developer to whom the key was issued.

Following is pseudogrammar that illustrates the construction of the Authorization request header. (In the example, \n means the Unicode code point U+000A, commonly called newline).


Authorization = NorskAccessKeyId + ":" + Signature;
Signature = Base64( HMAC-SHA1( YourSecretAccessKeyID, UTF-8-Encoding-Of( StringToSign ) ) );
StringToSign = HTTP-Verb + "\n" +
    ToLowerCase(Content-MD5) + "\n" +
    Content-Type + "\n" +
    Date + "\n" +
    HTTP-Resource;

HMAC-SHA1 is an algorithm defined by RFC 2104 - Keyed-Hashing for Message Authentication . The algorithm takes as input two byte-strings, a key and a message. For Norsk request authentication, use your secret access key (YourSecretAccessKeyID) as the key, and the UTF-8 encoding of the StringToSign as the message. The output of HMAC-SHA1 is also a byte string, called the digest. The Signature request parameter is constructed by Base64 encoding this digest.

Time Stamp Requirement

A valid time stamp (using either the HTTP Date header or an x-date alternative) is mandatory for authenticated requests. Furthermore, the client timestamp included with an authenticated request must be within 30 minutes of the Norsk system time when the request is received. If not, the request will fail with the RequestTimeTooSkewed error code. The intention of these restrictions is to limit the possibility that intercepted requests could be replayed by an adversary. For stronger protection against eavesdropping, use the HTTPS transport for authenticated requests.

Some HTTP client libraries do not expose the ability to set the Date header for a request. If you have trouble including the value of the 'Date' header in the canonicalized headers, you can set the timestamp for the request by using an 'x-date' header instead. The value of the x-date header must be in one of the RFC 2616 formats (http://www.ietf.org/rfc/rfc2616.txt). When an x-date header is present in a request, the system will ignore any Date header when computing the request signature. Therefore, if you include the x-date header, use the empty string for the Date when constructing the StringToSign. See the next section for an example.

Authentication Examples

The examples in this section use the (non-working) credentials in the following table.

ParameterValue
NorskAccessKeyId MISCACCEXAMPLE
NorskSecretAccessKey wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

In the example StringToSigns, formatting is not significant, and \n means the Unicode code point U+000A, commonly called newline. Also, the examples use "+0000" to designate the time zone. You can use "GMT" to designate timezone instead, but the signatures shown in the examples will be different.

Example Label GET

This example gets an object from the johnsmith bucket.

RequestStringToSign
GET /shipment/123/label HTTP/1.1
Date: Tue, 27 Mar 2007 19:36:42 +0000
Authorization: MISCACCEXAMPLE:vHhzsjuRLTLTAamvWFsSeI9Mltc=
GET\n
\n
\n
Tue, 27 Mar 2007 19:36:42 +0000\n
/shipment/123/label

REST Request Signing Problems

When REST request authentication fails, the system responds to the request with an XML error document. The information contained in this error document is meant to help developers diagnose the problem. In particular, the StringToSign element of the SignatureDoesNotMatch error document tells you exactly what request canonicalization the system is using.

Some toolkits silently insert headers that you do not know about beforehand, such as adding the header Content-Type during a PUT. In most of these cases, the value of the inserted header remains constant, allowing you to discover the missing headers by using tools such as Ethereal or tcpmon.