Introduction And Lesson Overview

Welcome back! In the previous lesson, you learned how to generate secure API keys, store them safely using hashing, and create an endpoint for users to request new keys. Now that you know how to create and manage API keys, it is time to learn how to use them to authenticate requests to your API.

In this lesson, you will integrate API key authentication into your application using Express middleware. You will see how to validate API keys, check their format, compare them securely with stored hashes, and handle expired keys. You will also learn how to combine API key authentication with JWT authentication, giving your API the flexibility to support both methods. By the end of this lesson, you will be able to implement robust API key authentication and understand how it fits into a secure API architecture.

Overview Of API Key Middleware

Before diving into the code, let’s quickly review what middleware is and why it is important for authentication. In Express, middleware functions are pieces of code that run before your route handlers. They can inspect, modify, or reject incoming requests. Middleware is the perfect place to handle authentication because it allows you to check credentials before any sensitive logic runs.

API key authentication middleware is responsible for checking if a request includes a valid API key and, if so, allowing the request to proceed. If the key is missing or invalid, the middleware stops the request and returns an error. This approach helps protect your API from unauthorized access and ensures that only users with valid keys can use your service.

Validating API Key Format And Extracting The Key

When a client sends a request to your API, they include their API key in the X-API-Key header. Before you check if the key is valid, you should first make sure it is in the correct format. In our example, every API key starts with the prefix pb_ and is followed by 64 hexadecimal characters, making the total length 67 characters.

Here is the code that checks the format:

If the key does not match this format, the middleware immediately returns an error. This helps prevent unnecessary database lookups and can stop some simple attacks. Once the format is confirmed, the middleware removes the pb_ prefix to get the raw key, which is what was originally generated and given to the user. This raw key is what you will compare against the stored hashes.

For example, if the incoming header is:

The middleware will extract 4f3c2e1a1234567890abcdef1234567890abcdef1234567890abcdef12345678 for verification.

Securing The Authentication Process With Hash Comparison

Now that you have the raw key, you need to check if it matches any of the active API keys stored in your database. Remember from the previous lesson that you never store the raw key itself — only a hash of the key, using bcrypt. To verify the key, you use bcrypt's compare function, which checks if the provided key, when hashed, matches the stored hash.

Here is the relevant part of the middleware:

Notice that we continue checking all keys even after finding a match. This prevents timing attacks, where an attacker could measure how long it takes for your server to respond and use that information to guess valid keys. By always checking the same number of hashes, the response time remains consistent regardless of whether a match is found early or late in the list.

If no match is found, the middleware returns a 401 Unauthorized error. This means the key is either invalid or does not belong to any active user. If a match is found, the request can continue. This process ensures that even if someone gains access to your database, they cannot use the hashes to authenticate because bcrypt hashes are one-way and cannot be reversed.

If the key is missing or invalid, the response might look like this:

Handling Expired Keys And Attaching User Information

Even if an API key is valid, it might be expired. Each key has an expiresAt field, and the middleware checks if the current date is past this expiration. If the key is expired, the request is rejected with an error message and the expiration date.

For example, if a key is expired, the response could be:

If the key is valid and not expired, the middleware attaches the user and API key information to the request object. This allows downstream route handlers to know which user is making the request and which key was used. For example, after authentication, you can access req.user and req.apiKeyId in your route handlers. This is useful for logging, rate limiting, or applying user-specific logic.

Flexible Authentication: Combining API Key And JWT Strategies

In many real-world applications, you may want to support both API key and JWT authentication. For example, your web frontend might use JWTs, while third-party integrations use API keys. The middleware can be designed to check for an API key first, and if none is found, fall back to checking for a JWT in the Authorization header.

Here is how the flexible authentication middleware works:

This approach gives your API flexibility and makes it easier to support different types of clients. It also allows you to gradually migrate from one authentication method to another or to offer both for different use cases.

Summary And Next Steps

In this lesson, you learned how to integrate API key authentication into your Express application using middleware. You saw how to validate the format of API keys, extract and verify them securely using bcrypt, handle expired keys, and attach user information to requests. You also learned how to combine API key and JWT authentication for a flexible and secure API.

You are now ready to practice these concepts in the hands-on exercises that follow. Remember, on CodeSignal, all the necessary libraries are pre-installed, so you can focus on writing and testing your code. Keep up the great work — these skills are essential for building secure APIs that can support a variety of clients and use cases.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal