Wednesday, May 18, 2011

Amazon Web Services (AWS) URL Authentication

There are two types of web service requests that can be made to Amazon Web Services (AWS).

  • Anonymous requests are made to freely available services using an Access Key ID which is issued when consumers sign up for an account.  This key is included as a request parameter in all requests made to AWS.
  • Authenticated requests must contain a request signature, in other words the URL must be signed using a generated digital signature.

    AWS Access Identifiers are an Access Key ID which is your identity/username and a Secret Access Key which is your password.  The Secret Access Key must be kept secret and is never used in requests, it is instead used together with an encryption algorithm during the signing process.  The Secret Access Key is a 40 character alphanumeric sequence issued to consumers by AWS.



    A Recipe for Signing URL Request’s to AWS

    1)  Construct your request URL.


    The following is a dummy URL

    http://aws.amazon.com/onca/xml?Service=AWSDummyService&AWSAccessKeyId=00000000&Operation=DummySearch&ResponseGroup=DummyInfo,TopSellers,NewReleases&Version=2011-05-05

    2)  TimeStamp your URL.

    Attach a time stamp to the end of your URL.

    http://aws.amazon.com/onca/xml?Service=AWSDummyService&AWSAccessKeyId=00000000&Operation=DummySearch&ResponseGroup=DummyInfo,TopSellers,NewReleases&Version=2011-05-05&TimeStamp=2011-5-03T14:22:58Z

    For more info on UTC format TimeStamp, see the link below.

    http://en.wikipedia.org/wiki/Unix_time

    3)  URL encode any reserved characters used by query parameters.

    The ResponseGroup parameter contains comma’s and the TimeStamp parameter contains colons, comma’s and colons are reserved characters. To URL encode a reserved character, use the hex digit pair corresponding to the reserved character’s ASCII value, then precede the hex digit pair with a ‘%’.

    Reserved Character              Hex Digit Pair
              ,                                        %2C
              :                                        %3A

    The URL encoded dummy URL:

    http://aws.amazon.com/onca/xml?Service=AWSDummyService&AWSAccessKeyId=00000000&Operation=DummySearch&ResponseGroup=DummyInfo%2CTopSellers%2CNewReleases&Version=2011-05-05&TimeStamp=2011-5-03T14%3A22%3A58Z

    4)  Re-arrange URL query parameters in byte order to produce the canonical string.


    Capital letters come before lower case letters. A parameter name beginning with the capital letter 'D' precedes a parameter name beginnig with 'a', the names are NOT in alphabetical order.

    Dummy URL query parameters in byte order:

    AWSAccessKeyId=00000000&Operation=DummySearch&ResponseGroup=DummyInfo%2CTopSellers%2CnewReleases&Service=AWSDummyService&TimeStamp=2011-5-03T14%3A22%3A58Z&Version=2011-05-05

    The above is the canonicalized query string used to generate a signature.

    5)  Prepend Verb, Host and Path lines (preceding canonicalized query string) with a line break.

    HTTP Verb – GET, PUT, POST, DELETE or other
    Host - aws.amazon.com
    Path - /onca/xml (if the path is empty, use a / in its place)

    Each of the verb, host and path values must be on separate lines, and they must precede the canonicalized query string.

    6)  The signing string in full.

    PUT
    aws.amazon.com
    /onca/xml
    AWSAccessKeyId=00000000&Operation=DummySearch&ResponseGroup=DummyInfo%2CTopSellers%2CnewReleases&Service=AWSDummyService&TimeStamp=2011-5-03T14%3A22%3A58Z&Version=2011-05-05

    7)  Compute digital signature using signing string, Secret Access/Signing Key and a hash algorithm.

    The encryption algorithm can be HMAC SHA1 or SHA256. Amazon provides code samples in a variety of languages available to download for their Flexible Payment Service, the samples include code for generating digital signatures, see the following link.

    http://docs.amazonwebservices.com/AmazonFPS/2008-09-17/FPSBasicGuide/index.html?APPNDX_CodeSamples.html

    For more information on the Secure Hash Algorithm (SHA) see the following link.

    http://en.wikipedia.org/wiki/SHA_hash_functions

    8)  URL encode reserved characters in the signature.

    + and = characters in the signature must be replaced by hex digit pairs.

    9)  Create a signed request by attaching the signature to the end of the request URL.


    http://aws.amazon.com/onca/xml? AWSAccessKeyId=00000000&Operation=DummySearch&ResponseGroup=DummyInfo%2CTopSellers%2CnewReleases&Service=AWSDummyService&TimeStamp=2011-5-03T14%3A22%3A58Z&Version=2011-05-05&Signature=URLencodedSignature

    The above recipe can be used for Amazon's Product Advertising API and Amazon's Flexible Payment Service. For more information on the product advertising API see this link.

    http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?CHAP_Intro_AAWS.html

    Sending a signature as a URL query parameter is not the only way to sign requests, a signature can be sent instead by using the Authorization header.  See below for an explanation on how this is achieved using Amazon's S3 storage service.


    Sending signed requests to Amazon S3 storage service

    If the signature is sent as a header, it must be set out as follows:

    Authorization: AWS AWSAccesskeyId : generatedSignature

    When using an Authorization header for authentication, the format of the signing string should be as follows:

    VERB + \n

    + CONTENT-MD5 header value + \n

    + CONTENT-TYPE header value + \n

    + DATE header value + \n

    + AmzHeaders names and values in lower case and in alphabetical order + \n

    + Resource

    The format of a signing string when using query string authentication instead of an Authorization header involves a minimal change, replace the DATE header value with an Expires parameter value.  The Expires parameter value indicates when you want the signature to expire.

    The Amzheaders are any headers that start with x-amz-.

    The string to sign must be URL encoded (UTF-8 encoded).

    The content-type and content-md5 values are optional, if their values are not included in the string, newlines (\n) must still be included where the values would have been placed.

    The resource value is the bucket and key values separated by a '/ '.

    For more information on S3 signed requests see the following link:

    http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html