Next-auth: Session isn鈥檛 being expired correctly (client side)

Created on 2 Jul 2020  路  3Comments  路  Source: nextauthjs/next-auth

First of all, thank you to all the contributors for this project. Having gone through the course in reactsecurity.io, I think authN and authZ are such complex problems when it comes to decoupled backend and frontend, and not something I鈥檓 excited to implement from scratch.

Describe the bug
Unless you do a hard reload, the session doesn鈥檛 expire correctly client side.

To Reproduce

  • Clone the next-auth-example
  • Add a simple credential checker that always returns user
Providers.Credentials({
  name: 'Credentials',
  credentials: {
    username: { label: 'Username', type: 'text', placeholder: 'jsmith' },
    password: { label: 'Password', type: 'password' },
  },
  authorize: async (credentials) => {
    const user = { id: 1, name: 'J Smith', email: '[email protected]' }

    return Promise.resolve(user)
  },
})
  • Set options.session.maxAge to something short like 5 (seconds).
  • Navigate around and see that protected page is handled correctly, while header doesn鈥檛

Or clone the following repo that does exactly the above.

https://github.com/ryanditjia/next-auth-session-expiry-bug

Expected behavior
Session should expire correctly on the client-side too.

Screenshots or error logs
image

Additional context

Documentation feedback
Documentation refers to searching through online documentation, code comments and issue history. The example project refers to next-auth-example.

  • [X] Found the documentation helpful
  • [ ] Found documentation but was incomplete
  • [ ] Could not find relevant documentation
  • [X] Found the example project helpful
  • [ ] Did not find the example project helpful
bug stale

All 3 comments

Thanks for taking the time to submit this.

  • Sessions do expire correctly, but the state change is not reflected in the client unless the client is configured appropriately.
  • This is not a bug in NextAuth.js, it is intended behaviour in a Single Page App with the default session expiry settings.
  • The example project with the protected page is a beta release and this is also that expected behaviour in it in that release.

Client Max Age

You can set clientMaxAge option in the Provider in _app.js to tell the client how often to update the session state.

For example, if you set it to 5 * 60 the client will refresh the client state (at least) every 5 minutes. If your session expiry is longer than this (e.g. 10 minutes) then the client session will not expire, as long as any window or tab for the site in the client remains active.

As long as you set this value to something reasonable (shorter than the session max age), the session will keep rolling as long as they have an active window. If they close a window and re-open it, then the session will be either expired (and they will be signed out in the UI) or else it will be extended (and they will still be signed in in the UI).

If they actively signs out out in a browser, they will be logged out of all windows/tabs.

getSession()

If you want the UI to _never_ be out of sync before rendering, you can use getSession() and make it a blocking call on page render to ensure you check a session before rending a page. Doing this will impact your site performance.

Context / Plans

In future we might change the behaviour of clientMaxAge to make it only revalidate as needed (as version 1 did) which provides some cost/performance savings over fixed poll period. However, how want to handle authentication is always tradeoff, and some people will prefer stale-while-revalidate and some will prefer to use blocking calls.

It's a little easier to understand the impact and tradeoffs when using real world values for settings and how and when this will happen. Typically in popular sites session expiry time is measured in days or months. Some sites like banks use shorter windows (5-15 minutes) but that's at the extreme end of the scale. For context, the default session expiry time is 30 days.

It comes down to can either check session state in a blocking way (and accept the performance and cost impact) or you can accept that sometimes you will render stale data in the UI first. I am sure we will do more enhancements to reduce instances of stale UI state (including updating in the background after initial render) but the current behaviour is as expected.

Thank you for the thorough answer. My example is on the extreme end, and I think it鈥檚 a fair tradeoff in a real world setting.

@ryanditjia While doing some refactoring for the version 3 beta, I was thinking about your comments.

I've incorporated them into v3 and it includes much more sophisticated behaviour, including new clientMaxAge behaviour, a new keepAlive option and much improved multi-window and event based syncing, that supports very short session expiry times really well.

There is some more info and some detail in https://github.com/iaincollins/next-auth/issues/384

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MelMacaluso picture MelMacaluso  路  3Comments

ghoshnirmalya picture ghoshnirmalya  路  3Comments

SharadKumar picture SharadKumar  路  3Comments

eatrocks picture eatrocks  路  3Comments

readywater picture readywater  路  3Comments