This section is for client developers interested in learning about the API client authentication protocol specification for signing HTTP request messages. The specification below outlines how to implement a custom HTTP request signing function in your client code. Reference implementations of the API client authentication protocol are provided as open source on GitHub.
We strongly encourage you to use the existing libraries listed on the OPEN Source Clients page rather than writing your own, as those have been tested and verified, and are available in most modern programming languages.
The OPEN API client authentication protocol ensures that an OPEN API HTTP request message is valid and contains correct:
- Service Consumer Domain
- HTTP Authorization Header
Each of these aspects of the request message is specified below.
Service Consumer Domain
The HTTP host header must contain a valid service consumer domain as issued by Akamai Luna Control Center. The service consumer domain is the base URL.
The first path element in the request URI must be a valid endpoint of the service API. Each API has its endpoint documented in API Catalog. For example, /diagnostic-tools/.
HTTP Authorization Header
The HTTP authorization header MUST be included in the request message in the format defined below for EdgeGrid v1.
The Authorization header starts with the signing algorithm moniker (name of the algorithm) used to sign the request. The moniker below identifies EdgeGrid V1, hash message authentication code, SHA–256 as the hash standard.
This moniker is then followed by a space and an ordered list of name value pairs
with each field separated by a semicolon
Authorization Header Fields
After the signing algorithm moniker, the client_token, access_token, and timestamp are concatenated into the authorization header value.
Must be assigned a valid client token.
Must be assigned a valid access token.
Must be assigned the UTC time when the request is signed. It is in the format of
yyyyMMddTHH:mm:ss+0000: the year as a 4-digit decimal number including century, followed by the month as a decimal number with a range of 01–12, followed by the day of the month as a decimal number with a range of 01–31, followed by a character
T, followed by the hour as a decimal number using a 24-hour clock with a range of 00–23, followed by the minute as a decimal number with a range of 00–59, followed by the second as a decimal number with a range of 00–60, followed by the timezone as hours offset from GMT. An example timestamp would be 20130703T19:38:41+0000.
NOTE: Akamai OPEN APIs are time sensitive! Ensure that the system your client runs on is synchronized with a Stratum 2 or better time source.
Must be assigned a nonce (number used once) for the request. It is a random string used to detect replayed request messages. A GUID is recommended.
Must be assigned the result of the EdgeGrid request signature (see below).
Here is an example HTTP authorization header, with line breaks added for readability:
Authorization:EG1-HMAC-SHA256 client_token=akaa-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx; access_token=akaa-xxxxxxxxxxxxxx-xxxxxxxxxxxxxx;timestamp=20130817T02:49:13+0000; nonce=dd9957e2-4fe5-48ca-8d32-16a772ac6d8f;signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
EdgeGrid Request Signature
The signature is the base64-encoding of the SHA–256 HMAC of the data to sign with the signing key.
The signing key is derived from the client secret. The signing key is computed as the base64 encoding of the SHA–256 HMAC of the timestamp string (the field value included in the HTTP authorization header described above) with the client secret as the key.
Data to Sign
The data to sign includes the information from the HTTP request that is relevant to ensuring that the request is authentic. This data set comprised of the request data combined with the authorization header value (excluding the signature field, but including the
; right before the signature field).
Request data fields:
- Request method (GET/PUT etc.) in upper case
- Scheme (http/https) in lower case
- Host from the Host header in lower case
- Relative URL that contains the path and query portions of the URL, exactly as it appears in the HTTP request line
- Canonicalized request headers
- Content hash of the request body for POST requests
The relative URL is the part of the URL that starts from the root path and includes the query string, with the handling of following special cases:
- If the path is null or empty, set it to
- If the path does not start with
/to the beginning.
Canonicalized Request Headers
The protocol does not support multiple request headers with the same header name. Such requests SHOULD be rejected during the signing process. Otherwise, EdgeGrid will not produce the intended results by rejecting such requests or removing all (but one) duplicated headers.
- Header names are case-insensitive per rfc2616.
For each entry in the list of headers designated by the service provider to include in the signature in the specified order, the canonicalization of the request header is done as follows:
- Get the first header value for the name.
- Trim the leading and trailing white spaces.
- Replace all repeated white spaces with a single space.
- Concatenate the name:value pairs with the tab (
\t) separator (name field is all in lower case).
- Terminate the headers with another tab (
NOTE: The canonicalized data is used for creating the signature only, as this step might alter the header value. If a header in the list is not present in the request, or the header value is empty, nothing for that header, neither the name nor the tab separator, may be included.
For example, a request with the following sample headers. NOTE: The
x-b headers are included as reference but are not required.
Host: akaa-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna-dev.akamaiapis.net x-a: va x-c: " xc " x-b: w b
Would result in a string to sign in a format like this:
GET\thttp\takaa-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna-dev.akamaiapis.net\t /sample-api/v1/property/?fields=x&format=json&cpcode=1234\tx-a:va\tx-b:w b\tx-c:" xc "\t\t\t EG1-HMAC-SHA256 client_token=akaa-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxx; access_token=akaa-xxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx; timestamp=20130819T13:01:23+0000;nonce=ac392096-8aa1-44fd-8c3b-f797d35a6736;
NOTE: The above “string to sign” data contains the list of fields separated with a horizontal tab escape code metacharacter
0x09in ASCII. The tab is chosen as it is illegal in all the fields (see rfc3986) except the headers where our canonicalization will remove any tabs.
The content hash is the base64-encoded SHA–256 hash of the POST body. For any other request methods, this field is empty. But the tab separator (
\t) must be included. The size of the POST body must be less than or equal to the value specified by the service. Any request that does not meet this criteria SHOULD be rejected during the signing process, as the request will be rejected by EdgeGrid.
Example Data to Sign
Given an HTTP GET request to the diagnostic-tools API to retrieve the list of locations:
the data to sign looks like this (
\t represents a tab, line breaks added for readability):
GET\thttps\takaa-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net\t /diagnostic-tools/v1/locations\t\t\tEG1-HMAC-SHA256 client_token=akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx; access_token=akab-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx; timestamp=20140402T18:05:06+0000; nonce=185f94eb-537c-4c01-b8cc-2fa5a06aee7f;