TL;DR
This guide explains how to implement AWS Signature Version 4 (SigV4) authentication for secure communication with AWS services. It covers the key steps involved in creating a signed request, including calculating the signature and adding it to your HTTP headers.
1. Understand the Core Concepts
AWS SigV4 provides a robust method for authenticating requests made to AWS services. It uses asymmetric cryptography (HMAC-SHA256 in this case) to ensure request integrity and authenticity. The process involves:
- Region: The AWS region you’re interacting with (e.g., eu-west-1).
- Service: The specific AWS service you’re using (e.g., s3, ec2).
- Credential Scope: Defines the date range for which the signature is valid.
- Canonical Request: A standardized version of your HTTP request.
- String to Sign: A string derived from the canonical request and credential scope.
- Signature: The HMAC-SHA256 hash of the string to sign, calculated using your AWS secret access key.
2. Prerequisites
- An active AWS account with appropriate IAM permissions.
- Your AWS Access Key ID and Secret Access Key. Keep your Secret Access Key secure!
- The AWS region you will be using.
3. Construct the Canonical Request
This is a crucial step. The canonical request represents your HTTP request in a standardized format.
- HTTP Method: (e.g., GET, POST, PUT).
- Canonical URI: The path portion of the URL, encoded according to RFC 3986.
- Canonical Query String: The query string parameters, sorted alphabetically and encoded.
- Canonical Headers: HTTP headers (sorted alphabetically), excluding those related to authentication. Lowercase header names are required.
- Payload: The request body, if any.
Example Canonical Request:
GET
/my-bucket/my-object?param1=value1¶m2=value2
host:example.s3.amazonaws.com
x-amz-date:20240126T120000Z
4. Create the String to Sign
The string to sign combines information from the credential scope and canonical request.
- Credential Scope: Format is
{date}/{region}/service/aws4_request(e.g.,20240126/eu-west-1/s3/aws4_request). - Hash the Canonical Request: Calculate the SHA256 hash of the canonical request using a secure hashing algorithm.
The string to sign is then constructed as follows:
HMAC-SHA256( (date) + credential_scope + HMAC-SHA256(canonical_request))
5. Calculate the Signature
Use your AWS Secret Access Key to calculate the HMAC-SHA256 hash of the string to sign.
Example (using Python):
import hmac
import hashlib
import datetime
secret_key = b'YOUR_SECRET_ACCESS_KEY'
date = '20240126'
string_to_sign = b'...' # Replace with your actual string to sign
hash_object = hmac.new(secret_key, string_to_sign, hashlib.sha256)
digested = hash_object.hexdigest()
print(digested)
6. Add the Signature to Your HTTP Request
Include the following headers in your request:
- Authorization:
AWS4-HMAC-SHA256 Credential={access_key}/credential_scope/aws4_request, SignedHeaders=host;x-amz-date, Signature={signature} - X-Amz-Date: The date used in the credential scope (e.g.,
20240126T120000Z).
Example Authorization header:
Authorization: AWS4-HMAC-SHA256 Credential=ASIAIOSFODNN7EXAMPLE/20240126/eu-west-1/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=e68b9f...
7. Testing and Debugging
- Use a tool like Postman or curl to send your signed request.
- Verify that the AWS service accepts the request without authentication errors (403 Forbidden).
- Double-check all steps, especially the canonical request construction and signature calculation.