Search code examples
securitycallbackjwtnext-authexpress-jwt

Set expiration and automaticaly refresh JWT token in Nextauth.js


Best practice for JWT expiration period is somewhere around 15 minutes.

Using Nextauth.js (4.17.0) I have noticed that despite setting MaxAge property session token only looks like having expiration set, but in final when I decode Base64 the token it has not expiresIn set (!!! I can copy the token and use it for obtaining data from BE anytime). enter image description here

When I try set expiresIn as part of jwt.SignOptions

const jwtCallback = {
    encode: async ({ secret, token }) => jwt.sign(token, secret, { algorithm: 'HS512', expiresIn:'Whenever' }),

I get Error: Bad "options.expiresIn" option the payload already has an "exp" property.

Also, I want to periodically regenerate the token, so once it has expired I am already using another token. For that purpose I was trying to set different properties for session callback such as keepAlive, clientMaxAge, maxAge but no result for that.

I also saw here https://github.com/nextauthjs/next-auth/issues/5652 and https://github.com/nextauthjs/next-auth/issues/796 lot of comments where people similarly struggling with it.


Solution

  • Setting the expiration of the JWT token for me only works when I add it during JWT-callback like this:

    async jwt({ token, profile }) {
    ...
    token.exp = Math.round(Date.now() / 1000) + JWT_TOKEN_EXPIRES_IN_SECONDS;
    ...
    return token;
    

    Regenerating a new JWT token can be achieved with setting refetchInterval of SessionProvider component like this:

    <SessionProvider refetchInterval={JWT_TOKEN_REFETCH_INTERVAL_SECONDS}>

    Note (using also latest next-auth 4.24.7): when the window loses focus in Chrome after two minutes/several refetches refetchInterval is changed by the library to 60s, despite user settings