restsecurityapi-key

How to safely store API Keys in a database for a REST API?


I'm building a REST API that uses API keys for authentication. I want to ensure that these API keys are stored securely in my database. If I were storing user passwords, I would use Argon2id for hashing. For other types of sensitive user data that require decryption, I would consider using AES encryption.

However, I'm unsure about the best practices for storing API keys. Specifically, I want to know:

  1. Should I hash API keys before storing them in the database, similar to user passwords?
  2. If hashing is recommended, what algorithms are best suited for this purpose?
  3. Are there any specific considerations or best practices for securely storing and managing API keys that differ from handling passwords or other sensitive data?

I reviewed the OWASP guidelines but couldn't find a definitive recommendation on this topic.


Solution

  • An API key is a password. It has different characteristics than a typical human password, but it is a string of characters that will allow the bearer to authenticate.

    So it should be:

    1. Totally random, not derived from the account ID or any other identifier
    2. Stored using a one-way function, Argon2id with the recommended parameters is fine, but bcrypt and salted SHA2-256 are popular choices.
    3. Automatic rotation of API key on first use
    4. Possible for an administrator to change the API key in case of compromise.
    5. Possible to change the one-way algorithm at deployment time. Storing the algorithm used is one way to do it, but you might get away with deducing the algorithm from lenght of the one-way image you stored.

    Crypto agility

    You must be able to change the algorithm at deploy time. I would use the lenght of the image to know what algorithm was used, leaving to my future self the trouble of removing an extra, unused random character added to the image in case you have to switch to an algorithm that has the same output lenght.

    This table will give you a sense of the time it takes to brute force a bcrypt'd API key with high end hardware. If you are worried about nation state attack, add a few characters to your API key.

    Automatic rotation

    Whoever comes across the API key will know it. Your system should have an API endpoint that will exchange a temporary API key (known by administrators and developers) with the real API key.

    The protocol is simple :

    1. When an API call is made with an API that needs to change, you return a 401 error code.
    2. The application has logic to handle the error by calling the "renew key" API.
    3. The application gets a new API key and stores it without human intervention
    4. The API call is retried.

    Change the API key in case of compromise

    You can use the mechanism above to implement rotation of the key by an administrator. They just go in, change the API key and are done. The key does not have to be shown to them.

    If you believe the API key was compromised, then you are back to the initial onboarding process. An administrator will be shown the new API key, passed along to developpers and configured in the application. Using it will return a 401 that will trigger the process above.

    +If you developers can easily read the key from the production configuration, that is a different problem.