Secure protected API with HMAC! Next Level of API Keys 🔐
Tags: api, webdev, security, backend
Published: 2024-03-31 09:42:24

Is using API Keys enough to protect private APIs? Certainly not. The way API Keys work is by checking and validating whether the request sent by the client contains an API key, which is usually embedded in the header or query request. If the API key exists and is valid, the request is allowed, otherwise not.

This simple method may sound secure because only someone with a valid API key can access it. However, there's a security aspect that allows someone to steal the API key. The API Keys method embeds the API key directly into the header or query of the request, allowing others to see the content inserted into that request. As a result, someone can intercept the request and steal the API key 😮.

![API Key exposed, source: Google Images](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xre48mqzvtblogdp01p.png)

There are many API authentication methods that can be used to protect private APIs, one of the most popular being **JWT **(JSON Web Token). This method requires the client to log in to the system and obtain a token to access the API. However, this method is sometimes not ideal for APIs that involve data sharing or matrix reports because the client must log in first and secure their token to access the API. It should be noted that JWT tokens are embedded in the header, which can also be intercepted and stolen by others.



**What is HMAC?**
Another authentication method to consider is **HMAC **(Hash-based Message Authentication Code). This method uses a Public key embedded in the header or query and a Secret key to calculate the hash of a request data. It is important to note that the secret key will not be embedded in the request but will be used for hashing the request data. The resulting hash (usually called the signature) is then embedded along with the public key. By implementing HMAC, the server will validate the request by comparing the hash value. If the hash values match, the request will be allowed, otherwise not.

The HMAC method depends on the similarity of the secret key and the hashing algorithm used. For example, using "this-is-super-secret-key" as the secret key and HmacSHA256 as the chosen hashing algorithm. Then the server and client must use the same secret key and hashing algorithm to verify that the request is authentic. With this technique, someone attempting to intervene in the request will not be able to use the same signature for another request.

**Pros and Cons**
Although using HMAC seems secure enough, there are still advantages and disadvantages to this method. It would be better if this method is combined with other security measures such as IP Locking, Rate Limiting, and so on. The advantages offered by this method are as follows:

- Data Integrity: ensuring secure communication by verifying the integrity of the request.
- Protection Against Unauthorized Access: the API can only be accessed by clients with a valid secret key.
   
The disadvantages of this method are as follows:

- Key management and social engineering: ensuring that the secret key is not leaked into the wrong hands.
- Performance overhead: verifying the signature by a server receiving too many requests will require higher computational resources.


**Auth Flow**
So what is the actual process of the HMAC method, is it simple or quite complicated? Let's look at the following diagrams to get an idea.

![Process of generating a Hash-based Message Authentication Code (HMAC)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rbm9gjxzwrknkso4gng4.png)
It looks easy, right? The request data is combined with the secret key to create the digest algorithm and then the HMAC is calculated. Okay, now take a look at the following diagram to see how the process goes.


![Auth flow with HMAC between client and server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pnbjmlb7aehn11xy9ymb.png)
1. Both the server and client agree on the public key, secret key, and algorithm to be used.
2. The client will create a signature based on the requested data with the secret key.
3. The client inserts the public key and signature into the header request.
4. The server receives the request and verifies it by replicating the signature creation with the data (taken from the header and body request) and the same secret key.
5. If the signature matches, the request will be allowed, and vice versa, if not, it will be returned with an error 401 (Unauthorized).


**How to code?**
Okay, now it's time for practice! Here is a simple pseudocode to implement the HMAC method. If you're interested in seeing actual program code using the Nest.js framework, please check the [following GitHub repository](https://github.com/Wildanzr/articles_hmac_auth).

```
PUBLIC_KEY = req.headers[x-api-key];
SIGNATURE_KEY = req.headers[x-signature-key]
REQUEST_DATA = req.body;

// Check if public key and signature exist
if (!PUBLIC_KEY && !SIGNATURE_KEY) {
  throw Error(401)
}

// Regenerate Signature
SERVER_SIGNATURE = generateSignature(PUBLIC_KEY, SIGNATURE_KEY, REQUEST_DATA)

// Verify Signature
if (SERVER_SIGNATURE == SIGNATURE_KEY) {
  return OK(200)
} else {
  return Error(401)
}
```

**Conclusion**
Hmm, so are you interested in implementing the next level of API Keys? By using the HMAC method, API security will be maintained with cryptographic principles that are impossible to reverse engineer (perhaps if Quantum Computing is operational, cryptographic algorithms will be different 😃).

Thank you for reading this article, hope it's helpful 📖. Don't forget to follow the account for the latest updates 🌟. See you in the next article 🙌.