When it comes to authenticate API clients, a common solution is to deliver an API key to each of your API clients.
As the API key – which is sent over on each API call – might be stolen and used to make API calls by a malicious 3rd party on your client app’s behalf, we recommend to deliver a secret key along with the API key (aka client identifier). Following method is applicable when calling an API from a server, not from a client.
This secret key will be used to create a temporary access token, which is unique for each call and will be sent along your API key. If the same call is replayed, this will generate an error, as the access token is meant to be used only once.
On the calling side, here is what your client apps need to do for each call:
Take the public API Key
- Take the Secret Key (should never be shared)
- Generate a ‘nonce’, which is a random number that can only be used once
- Generate the ‘timestamp’, which is the unix timestamp
- Generate the access token, which is created by hashing the API key as follows, using the hashing algorithm of your choice:
$apikey = hash_hmac('sha1', $APIKey, $secretKey.$timestamp.$nonce);To generate the HMAC variant of the message digest, we concatenate the secret key, timestamp and nonce.
- We call the API by sending over the API Key, the timestamp, the nonce and the generated access token. Beware of never sending your secret key.
On the server side, here is the protection you need to put in place:
- If the received timestamp parameter is older than 15 minutes (or any other arbitrary value), dismiss the call
- If the received timestamp is within the time range of 15 minutes, check if the combination of ‘API Key’, ‘access token’, ‘nonce’, and ‘timestamp’ already exists in your memory cache. If it does, dismiss the call. If it doesn’t, add this entry to your cache and process the call.
- Make sure your cache entries automatically expire after 15 minutes to not overload your memory cache.