Understanding Expiry of JWTs
Session management is at the heart of user authentication, ensuring that users remain securely logged in while maintaining a smooth experience. When working with NextAuth, its robust support for JWT-based tokens makes it a go-to solution for modern, scalable applications. However, fine-tuning session expiry with JWTs can sometimes feel overwhelming without a clear understanding of its configuration and behavior.
This blog will explore on how to set up token durations, manage expiry effectively, and align your settings to match your application’s security needs—all while keeping the focus on practical, actionable insights.
How NextAuth Manages JWT Sessions
By default NextAuth uses JWTs (JSON Web Tokens) to manage server-side authentication and session cookies to communicate authentication state to the client. To learn more about JWTs you can go visit jwt.io. Let’s break down how these components work together to handle user sessions securely and efficiently.
Token vs. Session Cookie
- Token: The server-side representation of the session. It contains the user’s authentication information and is generated based on the configuration of your NextAuth setup.
- Session Cookie: Sent to the user’s browser, this is an encrypted version of the token. It uses the
NEXTAUTH_SECRET
to ensure secure storage on the client side while preventing tampering.
These two elements work together: the token is used for validating user sessions on the server, while the session cookie keeps the user logged in on the client.
Default Expiry Settings
By default, NextAuth sets a maxAge
of 30 days for both:
- JWT Token (
jwt.maxAge
): The lifespan of the server-side token before it expires and the user must reauthenticate. - Session Cookie (
session.maxAge
): The time the session cookie remains valid on the client side.
These durations can be configured independently, allowing flexibility for applications that need different lifespans for server and client-side authentication states.
Customize Expiry
To align session durations with your application’s needs, NextAuth allows you to configure separate expiry durations for both the JWT token and the session cookie. This setup provides flexibility to balance security and user convenience.
For instance, you might want the JWT token (server-side) to remain valid for 14 days, while the session cookie (client-side) expires after 1 day. Here’s how you can configure this:
// [...nextauth].ts
import NextAuth from "next-auth";
import Providers from "next-auth/providers";
export default NextAuth({
providers: [
// Add your provider(s) here
// ...
],
callbacks: {
// Add your JWT or session callbacks here if needed
// ...
},
jwt: {
maxAge: 14 * 86400, // 14 days in seconds
},
session: {
maxAge: 1 * 86400, // 1 day in seconds
},
secret: process.env.NEXTAUTH_SECRET, // Ensure this is securely set
pages: {
signIn: "/login", // Custom login page
},
});
A general rule of thumb is to configure session cookie expiry equal to or less than the JWT token expiry. So in this example, the maximum validity of session cookie should be set to 14 days or less. Another thing to keep in mind is when you set the session cookie’s expiry to be less than the JWT token’s expiry, then it is good to implement rolling sessions i.e. modifying the expiry based on activity. Otherwise if you’ve implemented custom middleware validation for client’s session, then it would redirect user to the login page and ask them to authenticate which would generate a new token while the old token is still valid and isn’t expired.
Static vs. Rolling Sessions
When a session is created, its expiry time is set based on the maxAge
property. By default, static sessions will expire at the time set in the configuration. This means the session will remain active for the specified maxAge
(i.e., 1 day for our example) and will expire once that time is reached on client side, regardless of user activity.
In contrast, rolling sessions extend the session's expiry time each time the user makes a request or takes some action, thus "renewing" the session. This can be configured by updating the session's expires
value based on the latest activity. For example, in NextAuth, you can configure session renewal with the updateAge
property. This ensures that the session's expiry is refreshed based on user activity, allowing users to stay logged in as long as they are actively engaging with the app. The updateAge
setting determines how often the session is updated, in seconds. To add this:
jwt: {
maxAge: 14 * 86400, // 14 days in seconds
},
session: {
maxAge: 1 * 86400, // 1 day in seconds
updateAge: 6 * 3600 // 6 hours in seconds
},
This approach automatically keeps the session alive as long as the user is active, without manual intervention, pushing the expiry of the session cookie (in our case by 6 hours). If a user doesn’t interact within the last expiry that was set, the session expires. It is recommended to use rolling sessions instead of static sessions as this is the industry standard. Think about it, how long has it been since you logged into Gmail Or YouTube?
Debugging Tips
When managing sessions in NextAuth, you might encounter issues and to help you avoid them below are some debugging tips you can use.
- Inspect Cookies and Tokens: Use browser developer tools to inspect session cookie. Check if the
maxAge
andexpiry
properties are set as expected. - Use the NextAuth Debug Mode: Set
debug: true
in your NextAuth configuration to get detailed logs that can help identify issues with session management.jwt: {}, session: {}, debug: true,
- Log Session Data: Add a logger and see when it’s being updated or reset. Following is an example logger and if you have a custom logger added, then
debug: true
is ignored.import log from "logging-service" export default NextAuth({ ... jwt: {}, session: {}, logger: { error(code, metadata) { log.error(code, metadata) }, warn(code) { log.warn(code) }, debug(code, metadata) { log.debug(code, metadata) } } ... })
Best Practices
When configuring session expiry and management in NextAuth, following best practices ensures that your application remains secure, reliable, and user-friendly. Here are some key recommendations:
Set Appropriate Expiry Values
Balancing security and user convenience is crucial. Setting excessively long session expiry values could pose security risks, while too-short values might frustrate users for prompting to re-login. For example, sessions for general users could last 1 day, while sensitive sessions (e.g., admin) could have a much shorter duration.
Best Practice: Use maxAge
values tailored to the sensitivity of the data. For general users, 30 days might be acceptable, but for users with more critical roles or data access, use shorter time periods like 1 or 2 hours.
Use Secure Cookies
When using cookies, ensure that the secure
flag is set, particularly if your site uses HTTPS. This ensures that cookies are only sent over secure connections, mitigating risks of man-in-the-middle attacks.
Best Practice: Always set secure: true
for cookies in production environments. Additionally, use the sameSite
cookie attribute to help prevent cross-site request forgery (CSRF) attacks. You can read more information on how to set these properties here.
Implement Rolling Sessions Where Appropriate
Rolling sessions are ideal for keeping users logged in as long as they remain active. This approach, used by popular applications like Gmail, refreshes the session's expiry whenever the user interacts with the app. This enhances user experience by preventing unexpected logouts.
Best Practice: Use the updateAge
option in NextAuth to refresh the session expiration on user activity. Set updateAge
to a reasonable value, such as 1 day for general users and 1 hour for admin users, to maintain session validity during periods of activity.
Key Takeaways on Effective Session Management
That’s it folks! By understanding the role of session cookies and JWTs, configuring appropriate session cookie expiry, JWT expiry, and implementing strategies like rolling sessions, you can maintain both security and usability. Furthermore, leveraging best practices, such as using secure cookies, implementing logging, and monitoring session data, will help you identify and solve issues quickly, ensuring your application remains reliable. NextAuth provides flexibility to suit a variety of needs when managing user sessions. Keep experimenting with different setups to find the best configuration for your application, and remember to always keep security in mind.