Welcome to the first lesson of our course on API Key Authentication & Security. In this lesson, you will learn the basics of generating and securely storing API keys — a fundamental part of building secure web applications and APIs. API keys are unique codes that allow applications or users to access certain features or data. They are widely used to control and monitor access to APIs, and they help keep your services safe from unauthorized use.
By the end of this lesson, you will understand how to generate strong, random API keys, how to store them securely in your database, and how to set up an endpoint for users to create their own API keys. You will also learn about best practices for managing API keys throughout their lifecycle. This knowledge will prepare you for the hands-on exercises that follow, where you will practice these skills in a real coding environment.
Let's start by looking at the data model for API keys. In our example, we use SQLAlchemy, a popular ORM for Python, to define the ApiKey model. This model represents how API keys are stored in the database. Here is the code for the model:
Each API key has several important properties. The id is a unique identifier for each key. The userId links the key to a specific user in your system using a foreign key relationship. The name allows users to label their keys for easy identification. The keyHash stores a hashed version of the API key, which is important for security (we will discuss this sooner). The isActive field lets you enable or disable keys without deleting them, and expiresAt sets an expiration date for each key. This structure helps you manage API keys safely and efficiently.
When creating an API key, it is important to make sure it is random and hard to guess. In our example, we use Python's built-in secrets module to generate a secure key. Here is the relevant code:
The function secrets.token_bytes(32) generates 32 random bytes, which gives us 256 bits of entropy. This makes the key very difficult to guess or brute-force. We then convert these bytes to a hexadecimal string using the .hex() method, which is easy to store and use. Adding a prefix like pb_ helps identify the key as belonging to your application, which can be useful for debugging or logging.
Storing raw API keys in your database is risky. If your database is ever compromised, attackers could use those keys to access your services. To prevent this, we hash the API key before saving it. In our code, we use the bcrypt library for hashing:
Hashing transforms the original key into a fixed-length string that cannot be reversed. Even if someone gains access to your database, they cannot recover the original API key from the hash. When a user presents an API key, you can hash the provided key and compare it to the stored hash to verify its validity. This is the same approach used for storing passwords securely.
Now let's look at how we allow users to create new API keys. We use a FastAPI route that handles POST requests to /create. This route is protected by a JWT authentication function, which checks that the user is logged in and authorized. Here is the main part of the route:
Managing API keys is not just about generating and storing them. You should also think about their lifecycle. Each key in our model has an expiresAt field, which means keys will automatically become invalid after a certain date. The isActive field allows you to deactivate keys without deleting them, which is useful if a key is compromised or is no longer needed.
Here are some tips for managing API keys safely:
- Always hash
API keysbefore storing them. - Limit the number of active keys per user to reduce risk.
- Set expiration dates for keys and encourage users to rotate them regularly.
- Never log or display the raw
API keyafter creation. - Encourage users to store their keys securely, such as in environment variables or secret managers.
Following these practices will help keep your application and your users safe.
In this lesson, you learned how to design a secure API key model, generate strong random keys, hash them for safe storage, and create an endpoint for users to generate their own API keys. You also learned about best practices for managing API keys throughout their lifecycle.
You are now ready to move on to the hands-on practice exercises, where you will apply what you have learned in a real coding environment. Remember, on CodeSignal, all the necessary libraries are pre-installed, so you can focus on writing and testing your code. Great job reaching the end of this lesson! Keep up the good work, and let's continue building your skills in API key authentication and security.
