Understanding JWT Token Expiration vs. Cookie Expiration: Why Both Are Crucial for a Seamless User Experience
Table of Contents
- JWT Expiration (expiresIn)
- The Role of Cookies in Storing JWT Tokens
- Why JWT Expiration Alone Doesn’t Work
- Why You Need Both JWT and Cookie Expirations
- Setting Both Expirations: A Complete Example
- How the Browser Handles Both Expirations
- What Happens in Practice?
- Potential Issue with Session Cookies
- Conclusion: Why Both Expirations Matter
When implementing JWT (JSON Web Tokens) for user authentication, it’s common to set an expiration date for the token itself to limit its lifespan. However, there’s often confusion about how token expiration interacts with cookie expiration and why both need to be managed carefully for a seamless user experience. In this post, we’ll explain why you need to set expiration for both your JWT and the cookie that stores it and what happens when you don’t.
JWT Expiration (expiresIn)
When you generate a JWT token, you usually set an expiration period using the expiresIn option, like this:
const token = jwt.sign({ id: user._id, email: user.email }, process.env.JWT_SECRET, { expiresIn: '7d' });
In this case, the token is valid for 7 days ('7d'). This expiresIn setting defines how long the JWT itself remains valid. Once the expiration time is reached (7 days in this example), the token becomes invalid, and any requests that use it for authentication will be rejected by the server.
The Role of Cookies in Storing JWT Tokens
In most applications, JWT tokens are stored in the browser (typically in a cookie or local storage) so that they can be used to authenticate subsequent requests. However, how long the JWT token persists in the browser depends on how the cookie is configured.
- Session Cookies: These cookies do not have an expiration date set. They are deleted when the browser session ends (i.e., when the browser is closed).
- Persistent Cookies: These cookies have a specific expiration date and remain stored in the browser even after it’s closed, until the expiration date is reached.
Why JWT Expiration Alone Doesn’t Work
Let’s say you only set the JWT expiration with expiresIn: '7d' in the token generation, but you don’t specify a cookie expiration. In this case, the cookie that holds the JWT will likely be a session cookie (unless you specify otherwise). This means the cookie will only last for the duration of the browser session. When the user closes their browser, the session ends, and the cookie gets deleted.
Why You Need Both JWT and Cookie Expirations
- JWT Expiration (expiresIn): Ensures that the token itself is only valid for a certain period (e.g., 7 days). This protects your application from long-lived tokens that could be misused if stolen.
- Cookie Expiration: Ensures that the cookie itself persists for the desired amount of time (e.g., 7 days), even after the browser is closed.
Setting Both Expirations: A Complete Example
1. JWT Expiration
const token = jwt.sign({ id: user._id, email: user.email }, process.env.JWT_SECRET, { expiresIn: '7d' });
2. Cookie Expiration
Now, let’s ensure that the cookie storing the JWT is set to expire after 7 days. Here’s the code that sets the cookie expiration:
const DAYS_TO_EXPIRE = 7;
const expirationDate = new Date();
expirationDate.setDate(expirationDate.getDate() + DAYS_TO_EXPIRE); // Set cookie to expire in 7 days
const cookieOptions = {
httpOnly: true, // Prevents JavaScript from accessing the cookie
expires: expirationDate, // Set the cookie to expire in 7 days
path: '/', // Cookie available across the entire site
sameSite: 'lax', // Helps prevent CSRF attacks
};
if (process.env.NODE_ENV === 'production') {
cookieOptions.secure = true; // Ensures the cookie is sent over HTTPS in production
}
How the Browser Handles Both Expirations
JWT Expiration (expiresIn): Once the JWT expires after 7 days, the server will reject any requests using the expired token with an "Unauthorized" response, even though the cookie may still exist.
Cookie Expiration: By setting the expires attribute for the cookie, you tell the browser to store the JWT for 7 days. This ensures that the JWT remains available in the cookie, even if the browser is closed and reopened.
What Happens in Practice?
When the user logs in, the server generates a JWT token and sets the cookie with an expiration of 7 days.
The user can continue making requests using the JWT token, and the cookie will persist for 7 days.
If the user closes the browser and reopens it, the JWT is still stored in the cookie (since the cookie expires in 7 days).
After 7 days, the cookie will be deleted from the browser, and the server will reject the token as expired.
Potential Issue with Session Cookies
If you do not set a cookie expiration date and rely on session cookies, the token will be lost when the browser is closed. Therefore, for a better user experience, ensure that your cookie expiration aligns with the JWT expiration.
Conclusion: Why Both Expirations Matter
To ensure a seamless user experience while maintaining good security practices, always make sure both your JWT token and cookie have appropriate expiration dates. This ensures that your authentication system remains secure while providing a smooth and uninterrupted experience for users.