Signing API Requests

Importance of the Date Header

The value of the Date HTTP header is used as part of the request signing process to enforce the temporary state of signed requests. For this reason, the system clock on the client and server sides must be synchronized, up to an allowed time skew of ±360 seconds.

If the server receives an API request with a Date header value that represents more than 30 seconds of time difference (either before or after the server clock), the request will not be accepted.

The X-Zend Signature HTTP Header

In order to send authenticated API requests you are required to send the X-Zend-Signature HTTP header with each request. It must be in the following format:

X-Zend-Signature: <key name>; <signature>

Where <key name> is replaced with the key name, and <signature> is replaced with the calculated request signature.

 

There can be any number of whitespace characters before or after the separating semicolon.

Usage Example

Example:

X-Zend-Signature: Arch Stanton;
a0f9b1d61e21e796d78dccdf1352f23cd328...

Note:

The signature is expected to be 64 characters long, and is cut here for readability purposes.

Calculating the Request Signature

The request signature is a 64 digit long hexadecimal number with digits a-f in lower case, calculated using the following method:

  1. Concatenate the following values in order, separated by a colon (:), into a single string:
    1. The exact value of the Host HTTP header. In most cases this will be a string in the form "<host>:<port>". In some cases the colon and port are omitted. In any case, if the port is included in the Host header sent in the request, it must be included in the generated string.
    2. The Request URI, which is the path part of the full request URL, without the query string or host name.
    3. The exact value of the User-Agent request header.
    4. The exact value of the Date request header.
  2. Hash the generated string with the HMAC/SHA-256 function using the secret API key to obtain the request signature.

Examples

Creating a Signature

Usage Example

To create a signature:

<?php
/**
* Calculate Zend Server Web API request signature
* @param string $host Exact value of the 'Host:' HTTP header
* @param string $path Request URI
* @param integer $timestamp Timestamp used for the 'Date:' HTTP header
* @param string $userAgent Exact value of the 'User-Agent:' HTTP header
* @param string $apiKey Zend Server API key
* @return string Calculated request signature
*/
function generateRequestSignature($host, $path, $timestamp, $userAgent, $apiKey)
{$data = $host . ":" .$path. ":" .$userAgent. ":" .gmdate('D, d M Y H:i:s ', $timestamp) . 'GMT';
return hash_hmac('sha256', $data, $apiKey);
}

 

Additional Values

Usage Example

When sending the following API request:

POST /ZendServer/Api/findTheFish HTTP/1.1
Host: zscm.local:10081

User-agent: Zend_Http_Client/1.10
Accept: application/vnd.zend.serverapi+xml;version=1.0
Date: Sun, 11 Jul 2010 13:16:10 GMT
Content-type: application/x-www-form-urlencoded
Content-length: 19
lookInCupboard=TRUE

 

Using a key named “angel.eyes” with the following value:

9dc7f8c5ac43bb2ab36120861b4aeda8f9bb6c521e124360fd5821ef279fd9c7

 

The request parameters to be signed, concatenated into a string is:

zscm.local:10081:/ZendServer/Api/findTheFish:Zend_Http_Client/1.10: Sun, 11 Jul 2010 13:16:10 GMT

 

From this value, an HMAC/SHA-256 signature will be calculated using the API key. For example using the hash_hmac() PHP function:

785be59b7728b1bfd6495d610271c5d47ff0737775b09191daeb5a728c2d97c0

 

The final request, including the added X-Zend-Signature header, is (lines are broken for readability):

POST /ZendServer/Api/findTheFish HTTP/1.1

Host: zscm.local:10081
User-agent: Zend_Http_Client/1.10
Accept: application/vnd.zend.serverapi+xml;version=1.0
Date: Sun, 11 Jul 2010 13:16:10 GMT
Content-type: application/x-www-form-urlencoded
Content-length: 19
X-Zend-Signature: angel.eyes;
785be59b7728b1bfd6495d610271c5d47ff0737775b09191daeb5a728c2d97c0
lookInCupboard=TRUE

The server then proceeds to generate the same signature, based on the same data and same secret key. If the two signatures match, the request will be accepted.