Request Authentication
Authentication allows server to verify the integrity of the request and identify the sender. Based on the identity, access control, usage tracking and rate limiting can be enforced. This section describes how to build authorization signature for request.
Photon P3 REST endpoints use HMAC (Hash Message Authenciation Code) on top of HTTP scheme for authentication. In order to make request to Photon P3 service, you first acquire a P3 access key ID and a access key secret through P3 portal. Keep them in safe place so no one can fabricate your identity. After building an HTTP request, you concatenate selected fields form a string. HMAC of the string is calculated using your access key secret. The HMAC is the “signature” of your request. It is part of the Authorization
field in the HTTP header. When a P3 server receives a request, it performs the same signing process and compares the resulting signature against the one extracted the Authorization
header. If these two signatures match, the server can proceed to process the request with the authenticated identity. Otherwise, the request is denied.
The authentication header
The Photon P3 REST endpoints receives authentication data by using the standard HTTP Authorization
header. The header field value is P3 access key ID concatenated with request signature, deliminated by a colon.
Authorization: access_key_id:signature
The access key ID is a straight copy from what is given by P3 port. The signature is the BASE64 encoding of RFC 2104 HMAC-SHA1 of selected elements from the HTTP request being authenticated. P3 server uses the provided access key ID to find its matching access key secret and signs the request using the same procedure done by a client. The resulting signature is matched against the signature from the Authorization
header to verify the identity of the requester.
signature = BASE64( HMAC_SHA1( UTF8_Encoding(access_key_secret), UTF8_Encoding(string_to_sign) ) )
HMAC function takes two parameters. One is your access key secret. The other one is the string composed from selected parts of the request being authenticated. Both parameters should be UTF-8 encoded. The output digest of HMAC function is further encoded using BASE64 encoding scheme to be transferred through HTTP safely.
The string_to_sign
has 3 components, concatenated together with delimiter newline “\n”.
string_to_sign = positional_fields + "\n" +
canonicalized_p3_headers + "\n" +
canonicalized_uri
Positional fields
The positional_fields
are 4 field values concatenated together in fixed order with delimieter newline “\n”.
positional_fields = http_verb + "\n" +
content_md5 + "\n" +
content_type + "\n" +
date + "\n" +
The http_verb
is either GET
or PUT
. The content_md5
is the value from P3 specific HTTP header x-p3-content-md5
and falls back to standard header Content-MD5
if missing. Empty string “” is used if both headers are missing. The content_type
is the value from P3 specific HTTP header x-p3-content-type
and falls back to standard header Content-MD5
if missing. Empty string “” is used if both headers are missing. Finally, the date
value is a string representation of the request time in RFC3339 format. Request time is extracted from P3 specific HTTP header x-p3-unixtime
, which is a unix timestamp in seconds. If the header is missing, it falls back to standard HTTP header Date
. The date
is a required value and must be no later than 15 minutes to ensure freshness of a request.
Canonicalized P3 headers
The canonicalized_p3_headers
is generated by P3 specific HTTP headers using rules described below:
- Select all HTTP headers that have prefix “x-p3-“ in its name and convert names to lowercase.
- Sort selected headers lexicographically by header name.
- For each header name, corresponding values are concatenated together with delimiter “,”. Then further concatenate with head name using delimiter “:” with all whitespace trimmed. For example, a header “x-p3-example” has two values “foo” and “bar”, the concatenated result is “x-p3-example:foo,bar”.
- Finally, results for each header are concatenated together using newline “\n” as delimiter.
Canonicalized URI
The canonicalized_uri
identifies P3 object being accessed, similar to AWS S3.
canonicalized_uri = "/" + bucket_name + "/" + object_key
Both bucket_name
and object_key
are canonicalized with extra and repeated backslash removed. For example, bucket “example_bucket” and key “foo//bar” generate canonicalized URI “/example_bucket/foo/bar”.