Welcome back! So far, you have learned how to organize your backend code using a service layer and how to validate data in your Task Manager API. Now, it’s time to make your API more secure and easier to monitor.
APIs are often exposed to the internet, which means anyone can try to access them. Without security, someone could misuse your API or access sensitive data. Logging is also important because it helps you see what’s happening in your API — who is using it, when, and how. This is useful for debugging and for keeping your API safe.
In this lesson, you will learn how to:
- Protect your API using an API key.
- Log every request to your API for better monitoring.
By the end, your Task Manager API will be more secure, and you’ll have a record of every request made to it.
Before adding logging and API key security, let’s review how your current backend is structured:
- You have API routes under
/api/tasks
, which call functions from your taskService to interact with an in-memory array of tasks. - All task-related routes (GET, POST, PUT, PATCH, DELETE) are already implemented in
route.ts
files using the service layer. - Now, we’ll add middleware that runs before any of these routes are handled to:
- Check for a valid API key in the request.
- Log information about every request for debugging and security. This mirrors how real-world APIs typically handle request-level authentication and monitoring.
To protect your API, you can require clients to include a special key (an API key) in their requests. Only requests with the correct key will be allowed.
In Next.js, you can use middleware
to check for this key. Here’s how you can do it:
Explanation:
- The
middleware
function runs before your API routes. - It checks if the request path starts with
/api/tasks
. From the previous courses we know that we can change this logic to protect any other paths in your API — for example, if you add/api/admin
in the future. For now, we're securing just the/api/tasks
endpoints. - If it does, it looks for an
x-api-key
header in the request. - If the key is missing or incorrect, it returns a 401 Unauthorized response. In production, you'd typically use a longer and more secure key — and rotate it periodically. You may also want to log these unauthorized attempts for auditing and alerting.
- If the key is correct, the request continues.
Storing the API Key:
You should never hard-code secrets in your code. Instead, use environment variables. In your .env.local
file, add:
Logging helps you keep track of what’s happening in your API. You can log details like the time, method, path, user agent, and IP address of each request.
Let’s add logging to the middleware:
Explanation:
- We create a
log
object with useful information about the request. timestamp
records when the request happened.method
is the HTTP method (GET, POST, etc.).path
is the URL path.userAgent
tells you what kind of client made the request.ip
is the client’s IP address.- We print this log to the console.
Example Output:
This log will appear in your server’s console every time a request is made.
You may not want your middleware to run for every route in your app. Next.js lets you control this with a matcher
configuration.
Add this to your middleware.ts
:
Explanation:
- The
matcher
tells Next.js to only run this middleware for routes that start with/api/
. - This keeps your security and logging focused on your API, not your whole app.
Now that your backend expects an API key in every request to /api/tasks
, let’s look at how the frontend connects to this.
In your UI, you have an input field that lets users provide the API key manually:
This input updates the apiKey state, which is then used in all task-related fetch functions. Here's how a typical function looks:
This function does three things:
- Checks if the API key is set — if not, it logs an error and stops the request.
- Sends the request with the API key in the
x-api-key
header. - Logs the response to the browser console or log area in your UI.
This same pattern is used across other handlers (handleCreate
, handleUpdate
, handleDelete
, etc.).
🔒 This setup simulates how authenticated APIs are used in the real world — the client includes a secret token (in this case, the API key), and the server validates it via middleware.
🧪 You can test different behaviors by:
- Leaving the input blank → should trigger "Please provide the API key" warning.
- Entering an incorrect key → should trigger a 401 Unauthorized response from the backend.
- Entering the correct key → should result in a + console log from middleware.
In this lesson, you learned how to:
- Secure your Task Manager API using an API key and middleware.
- Log important details about every API request.
- Apply middleware only to your API routes using the matcher config.
These steps make your API safer and easier to monitor. Now, you are ready to practice these skills in the exercises that follow. Since this is the last lesson of the course, congratulations on making it to the end! You have built a solid foundation in backend development with Next.js. Keep experimenting and building — your journey as a developer is just beginning!
