Secure your REST API with HMAC
In a B2B scenario when using for instance REST between the entities you are going to need some means to authenticate the client. One way can be to issue client certificates and use TLS mutual authentication but that will enforce end to end encryption to your service which means you can't terminate the TLS connection in the edge (like the load balancer). For instance in AWS you will not be able then to use the Application Load Balancer, you will instead have to use the more "primitive" Network Load Balancer.
A much better option is to use some sort of API key or HTTP Basic authentication. But those approaches have a drawback that they are open for replay attacks. HTTP Digest authentication addresses that aspect but it is not very well supported and most likely you will need to have a state on the sever side too.
The best option is then to secure your endpoint with HMAC (Hashed based message authentication code). Basically you calculate the hash code of the request and the shared secret and pass that along the request. The receiver will do the same using the shared secret. And if the hash codes matches the authentication is a success. The shared secret isn't passed along in the request like in HTTP Basic authentication or if only an Accesskey was used. So in that sense it is similar to TLS mutual authentication. You can also think of the hash code as a signature.
The steps in the process are:
- Provision the shared secret key to client and server.
- Send the request body and add three headers 1) header with the client ID (access key), 2) header with the hash code of the shared secret key plus the current timestamp and plus for instance the request URL, and finally 3) header with the same timestamp.
- Server receives the request and check if client ID is valid and not revoked.
- Server checks the timestamp header and verify it isn't too old. This will mitigate a replay attack. If you suspect the time isn't fully synchronised between the client and the server you need allow for some slack here plus that the request takes some mills to process too.
- The server calculate the hash code the same way the client did using the timestamp in the header and verify that the hash code is the same as received.
This solution is simple to provision and is also replay resistance so it satisfies NIST SP 800-53 AC-17(10) and IA-2(8).
AWS APIs is also using HMAC for authentication. See AWS Signature Version 4 Python sample code.
Keep your endpoints safe!