Authenticating REST Requests

Topics

Every request you make to the Amazon CloudFront control API must be authenticated. AWS and others in the coding community provide tools that automatically sign your requests as required for CloudFront. For more information, go to the Amazon CloudFront Getting Started Guide or to the CloudFront sample code and libraries page. If you plan to write your own code to sign requests, then read this topic.

Comparison with Amazon S3

If you already know how authentication works for Amazon Simple Storage Service REST requests, then the information in this topic will be familiar to you.

Following are the main differences between how you authenticate CloudFront and Amazon S3 requests:

  • For CloudFront, you must use HTTPS

  • For CloudFront, the canonical string to sign is simply the value of the Date header (or the x-amz-date header if you include it in the request)

    Therefore, the value of the Authorization header is as follows:

    Authorization: "AWS" + " " + AWSAccessKeyID + ":" + 
                    Base64(HMAC-SHA1(UTF-8(Date), UTF-8(AWSSecretAccessKey)))

Overview of the Authentication Process

Authentication is how you prove your identity to the system. You must prove your identity in all your requests to the CloudFront control API. The following sections describe how.

The CloudFront REST API uses a custom HTTP scheme based on a keyed-HMAC (Hash Message Authentication Code) for authentication. The following figure and table describe the basic process for authentication.

Basic flow for request authentication

Process for Request Authentication

1

You create a string based on specific information in the request. For more information, see The String to Sign.

2

You calculate a signature using your AWS Secret Access Key, the string from task 1, and an HMAC-SHA1 algorithm.

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. For instructions on creating the signature, see Calculating the Signature.

3

You include the signature in the request and send the request to AWS using HTTPS (HTTP requests are not accepted).

For information about where to put the signature in the request, see The Authorization Header.

4

We check your signature.

When we receive your request, we fetch the AWS Secret Access Key that you claim to have and use it in the same way you did to compute a signature for the message. We then compare the signature we calculated to the signature you presented in the request. If the two signatures match, we accept and process the request. Otherwise, we reject the request and respond with an error message (for more information, see Authentication Errors).


[Note]Note

We also confirm the request time stamp is within 15 minutes of the AWS server time. For more information, see Fetching the Date.

The String to Sign

In the first task in the preceding process, you form a string. The string is simply the UTF-8 encoded value of the Date header in the request (e.g., Thu, 19 Nov 2009 19:37:58 GMT). Your request must include either the Date header, the x-amz-date header, or both (if both are present, we ignore the Date header when authenticating the request). You might decide to include the x-amz-date header if your HTTP client doesn't let you set the Date header.

The format you use for the header value must be one of the full date formats specified in RFC 2616 section 3.1.1. For example: Wed, 05 Apr 2006 21:12:00 GMT. For more information, go to the RFC 2616 specification.

Calculating the Signature

Calculating the value to include in the request is a simple procedure.

Calculating the Signature

  1. Calculate an RFC 2104-compliant HMAC-SHA1 hash, using the string (see The String to Sign) and your Secret Access Key as the key.

  2. Convert the resulting value to base64.

    The result is the signature you include in the request.

The following table shows a string, a fake Secret Access Key, and what the resulting base64 encoded signature would be.

String

Thu, 14 Aug 2008 17:08:48 GMT

Secret Access Key

/Ml61L9VxlzloZ091/lkqVV5X1/YvaJtI9hW4Wr9

Base64 encoded signature

4cP0hCJsdCxTJ1jPXo7+e/YSu0g=

The Authorization Header

To pass the signature to AWS, you include it as part of the standard HTTP Authorization header. You include both the signature and your AWS Access Key ID in the header using the following format.

Authorization: AWS <AWSAccessKeyId>:<Signature>

Note that there is a space after the AWS.

Following is an example REST request with the example signature calculated in the preceding section. The AWS Access Key ID (0PN5J17HBGZHT7JJ3X82) is fake.

POST /2009-12-01/distribution HTTP/1.1
Host: cloudfront.amazonaws.com
Date: Thu, 14 Aug 2008 17:08:48 GMT
Authorization: AWS 0PN5J17HBGZHT7JJ3X82:4cP0hCJsdCxTJ1jPXo7+e/YSu0g=
[Other required headers]

<?xml version="1.0" encoding="UTF-8"?>
<DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2009-12-01/">
  <Origin>mybucket.s3.amazonaws.com</Origin>
  <CallerReference>20091130090000</CallerReference>
  <Comment>My comments</Comment>
  <Enabled>true</Enabled>
</DistributionConfig>

Authentication Errors

If the signature we create based on your request and Secret Access Key doesn't match the signature you sent in the request, we return the following error.

<ErrorResponse xmlns="http://cloudfront.amazonaws.com/doc/2009-12-01/">
   <Error>
      <Type>Sender</Type>
      <Code>SignatureDoesNotMatch</Code>
      <Message>The request signature we calculated 
        does not match the signature you provided. 
        Check your AWS Secret Access Key and signing
        method. Consult the service documentation for details.
      </Message>
   </Error>
   <RequestId>a1170c87-d04d-47c9-964f-54e1a4883f4e</RequestId>
</ErrorResponse>

Fetching the Date

To avoid replays of your requests, AWS requires the time stamp in the request to be within 15 minutes of the AWS system time. To avoid clock synchronization errors, we recommend you fetch the current date from the CloudFront server and then use that as the time stamp for your request and the string for your signature.

To fetch the date

  • Send an unauthenticated GET request for the date resource.

    GET /date HTTP/1.1
    Host: cloudfront.amazonaws.com

We return the current server date as the value of the Date response header (note that the HTTP status code may or may not be a 200). The date uses the RFC 1123 format (e.g., Wed, 18 Nov 2009 17:08:48 GMT). For more information, go to the RFC 1123 specification.