HMAC Authentication

HMAC authentication is most suitable for large B2B integrations with high security demands. It provides a digital signature for each request that guarantees that the request hasn't been tampered with.

For this type of authentication a pair of private and public API tokens is used. This pair of tokens is generated and provided to a client during onboarding and is out of scope of this document. Tokens are the globally unique GUID identifiers of 128bit size.

Standard HMAC digital signature can be applied to all the requests and responses if configured for the client (see http://en.wikipedia.org/wiki/Hash-based_message_authentication_code). HMAC is included in each request coming from the client and each response returned to the client. This allows for verifying that requests and responses come from the stated parties and have not been tampered with.

High-Level Overview

  • Generate a public/private token pair for the customer

  • The public/private token pair is shared with the client during the "onboarding" phase. This is done via a manual process and does not involve any API or backend component

  • HMAC works as follows:

    • [CLIENT] Create the string to be hashed (hash candidate) from the request data. The following request data shall be used for hash candidate: HTTP method, request content, URI, timestamp

    • [CLIENT] Using the SHA2-256 algorithm and the private token, create the HMAC hash of the hash candidate

    • [CLIENT] Include HMAC hash and the timestamp used to generate it into the request

    • [SERVER] Check the timestamp in the request against the current server system time and validate that the difference between them is within a configurable range of time. Reject if time difference is out of range.

    • [SERVER] Using the public token and any of the other necessary identifier information, retrieve the private token from the database.

    • [SERVER] Generate the HMAC hash in exactly the same manner as created by the Client (see [a] and [b] above).

    • [SERVER] Compare the HMAC generated on the server with that received from the client. If they match, process the command. If they don't match, reject the request.

    • [SERVER] Generate a response and sign it with HMAC exactly as described above. This would allow customers to validate response if needed.

The following header should be included with every request for HMAC authentication:

// http request

Authorization: DXAPI principal="<API principal>",timestamp=<timestamp>,hash="<HMAC hash>"

Where:

  • API principal is the public API token of the client obtained during onboarding

  • timestamp is the timestamp used to calculate hash candidate, see (1) below, UNIX milliseconds since epoch

  • HMAC hash is the hash calculated at step (3) below, in BASE64 encoding.

For any request to the API, the client generates a HMAC hash for HMAC signature according to the following algorithm:

  1. Create a set of key-value pairs with the following keys and values separated by '=' exactly in the order provided in the table:

  1. Concatenate all the pairs above using the new line character ('\n') as a separator. Sample hash candidate:

// text

Method=GET
Content=
URI=/orders/334
Timestamp=1464264688310
  1. Calculate the HMAC hash by applying SHA2-256 algorithm to the hash candidate.

For any request to the API with the Authorization HMAC header set, the server:

  • Validates the correctness of the header

  • Validates that the timestamp is within the acceptable pre-configured range from the current timestamp

  • Generates the HMAC hash for the request similar to the client (see steps above) and compares the hash with the one received in request

  • Computes a response for the request

If it is configured that the server should send HMAC signature in response for this client, the server computes HMAC signature for the response and include the following header so that the client is also able to verify HMAC signature on its side:

// http request

X-HMAC-Signature: DXAPI principal="<API principal>",timestamp=<timestamp>,hash="<HMAC hash>"

Last updated