Part 66: Enhancing Your API with Secure Cookie Management and Environment Variables
[Pages] Authentication

In our previous discussions, we built a foundation for our API handler to authenticate users by sending login credentials to a CMS and returning user details or an error response. Now, let's take our API to the next level by securely managing cookies for session handling and utilizing environment variables for better configuration management.
Utilizing Environment Variables
Before diving into cookie management, let's ensure our code is clean and maintainable by using environment variables. This approach allows us to manage configuration details, such as CMS URLs, without hardcoding them into our application.
Step 1: Define the Environment Variable
In your .env file, define the CMS_URL variable:
CMS_URL=http://localhost:1337Step 2: Use CMS_URL in API Calls
CMS_URL in API CallsIn our API handler, we can access this environment variable and use it in our API calls to the CMS. This approach ensures that the base URL for our CMS is easily configurable.
// pages/api/login.js
import cookie from 'cookie';
import { fetchJson } from '../../lib/api';
const { CMS_URL } = process.env;
async function handleLogin(req, res) {
if (req.method !== 'POST') {
res.status(405).end(); // Method Not Allowed
return;
}
const { email, password } = req.body;
try {
const { jwt, user } = await fetchJson(`${CMS_URL}/auth/local`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ identifier: email, password }),
});
// TODO: Set JWT cookie
res.status(200)
.setHeader('Set-Cookie', cookie.serialize('jwt', jwt, {
path: '/api',
httpOnly: true,
}))
.json({
id: user.id,
name: user.username,
});
} catch (err) {
res.status(401).end(); // Unauthorized
}
}
export default handleLogin;Securely Managing Cookies
Now that we've set up our environment variables, let's focus on securely storing the JSON Web Token (JWT) in a cookie. This method enhances security by restricting access to the token.
Step 1: Installing the Cookie Library
To format cookies correctly, we use a library that handles serialization for us. Install the cookie package:
npm install cookieStep 2: Setting the Cookie
With the cookie library installed, we can serialize the JWT and set it as a cookie in our API response. The cookie should be set with specific attributes to ensure security.
Name and Value: The cookie's name is
jwt, and its value is the JWT received from the CMS.Path: Set to
/apito restrict the cookie to API routes.HttpOnly: Set to
trueto prevent JavaScript access, enhancing security.
Code Implementation
Here's how we set the cookie:
// pages/api/login.js
res.status(200)
.setHeader('Set-Cookie', cookie.serialize('jwt', jwt, {
path: '/api',
httpOnly: true,
}))
.json({
id: user.id,
name: user.username,
});Testing the API Route
With our enhancements, let's test the API route to ensure it works seamlessly.
Successful Login: A POST request with valid credentials should set the JWT cookie and return user details.
Invalid Credentials: A
401 Unauthorizedresponse is returned, and no cookie is set.
Verifying the Cookie
In your browser's developer tools, navigate to the "Network" tab. When you make a login request, you should see the Set-Cookie header in the response, and the JWT cookie should appear in the "Cookies" tab.
Conclusion
By leveraging environment variables and securely managing cookies, we've strengthened our API's configuration and security. This setup allows us to handle authentication tokens securely and flexibly adjust configuration settings. As we move forward, we'll continue to build upon this foundation, ensuring our application remains robust and secure. Stay tuned for more insights on how to effectively manage and utilize cookies within your Next.js applications!
Last updated