HMAC Authentication

Elgg’s RESTful API framework provides functions to support a HMAC signature scheme for API authentication. The client must send the HMAC signature together with a set of special HTTP headers when making a call that requires API authentication. This ensures that the API call is being made from the stated client and that the data has not been tampered with.

The HMAC must be constructed over the following data:

  • The public API key identifying you to the Elgg api server as provided by the APIAdmin plugin

  • The private API Key provided by Elgg (that is companion to the public key)

  • The current unix time in seconds

  • A nonce to guarantee two requests the same second have different signatures

  • URL encoded string representation of any GET variable parameters, eg method=test.test&foo=bar

  • If you are sending post data, the hash of this data

Some extra information must be added to the HTTP header in order for this data to be correctly processed:

  • X-Elgg-apikey - The public API key

  • X-Elgg-time - Unix time used in the HMAC calculation

  • X-Elgg-nonce - a random string

  • X-Elgg-hmac - The HMAC as base64 encoded

  • X-Elgg-hmac-algo - The algorithm used in the HMAC calculation

If you are sending POST data you must also send:

  • X-Elgg-posthash - The hash of the POST data

  • X-Elgg-posthash-algo - The algorithm used to produce the POST data hash

  • Content-type - The content type of the data you are sending (this can be application/x-www-form-urlencoded or multipart/form-data)

  • Content-Length - The length in bytes of your POST data

Elgg provides a sample API client that implements this HMAC signature: \Elgg\WebServices\ElggApiClient. It serves as a good reference on how to implement it.

Supported hashing algorithms

  • sha256: recommended

  • sha1: fast however less secure

  • md5: weak and will be removed in the future

POST hash calculation

When sending the POST data as Content-Type: application/x-www-form-urlencoded; the post hash needs to be calculated over all the post data using one of the supported hashing algorithms.

When sending the POST data as Content-Type: multipart/form-data; the post hash needs to be calculated over an empty string.

The result of the hashing needs to be reported in the X-Elgg-posthash header and the used hashing algorithm must be reported in the X-Elgg-posthash-algo header.

Advertencia

Since the POST hash isn’t calculated when using Content-Type: multipart/form-data; only use this when calling APIs that need an file input.

HMAC hash calculation

The overall HMAC needs to be calculated over the following data (in order) using the API secret as the HMAC secret and with one of the supported hashing algorithms:

  1. a UNIX timestamp, report this timestamp in the X-Elgg-time header

  2. a random string, report this string in the X-Elgg-nonce header

  3. the public API key, report this API key in the X-Elgg-apikey header

  4. the url query string (for example method=test.test&foo=bar)

  5. when the request is a POST add the posthash as reported in the X-Elgg-posthash header

The resulting string needs to be base64 encoded and then url encoded and be reported in the X-Elgg-hmac header. The used hashing algorithm needs to be reported in the X-Elgg-hmac-algo.

Hashing cache

For security reasons each HMAC hash needs to be unique, all submitted hashes are stored for 25 hours to prevent reuse.