Handling session expiration for LiveViews

A project I’m currently working on uses a basic setup of Phoenix Auth and LiewVIews.
So while some things may differ, the core part is implemented following the Phoenix guides on how to setup user authentication.

In this context we ran into and issue where, if a user stays connected to a LiveView for long enough their token will expire. But since the view is already instantiated and authenticated it remains untouched and logged in.

While there are a few approaches that come to mind handling this kind of issue …

  1. Checking authentication again for each user action
  2. Repeatedly checking the authenticity of the user by the LiveView
  3. Writing a gc for the tokens and disconnection LiveViews by hand

… I was wondering if there is a standard way of handling this kind of situation I overlooked when reading the documentation.

Not sure but maybe this would help you:
https://hexdocs.pm/phoenix_live_session/PhoenixLiveSession.html

Very interesting find. Though it seems like a different approach to store sessions.

On the other hand maybe its a good starting point to get into managing the session more actively and through this being able to disconnect stale LiveViews.

Thanks!

We’ve been doing this and it works just fine:

  • Have a GenServer/Oban job that runs every specified amount of time
  • Check for session tokens inserted before the desired time (so they’re expired)
  • Delete those tokens and broadcast the same disconnect as if the user clicked Sign out

The LV will re-connect and get redirected to login.

To not have the user disconnecting in the middle of something, we actually extended the functionality above by adding a “last_seen_at” timestamp to the UserToken that gets updated every time a full page reload happens or every X minutes if the user is actively using the app by using the “ifvisible.js” library.
(And also decreased the session validity time)

4 Likes

This is a clever solution, I am definitely going to borrow it for one of my projects

Very nice solution, that’s exactly what I had in mind with the garbage collector solution.

How do you handle separate sessions/tokens for each user?
In our case the LV is id’ed by the user id so if a user has multiple tokens and thus the gc of just one will disconnect all LV’s.
Did you have to handle this in anyway or am I missing something?

In any case thanks for the help!

If you follow the ‘phx.gen.auth’ path, the ‘live_socket_id’ is set to contain the token, so when you remove it and send the disconnect it should only affect one session.

If your ‘live_socket_id’ contains the user ID instead you’re right, all sessions will reload but only one should get redirected.

Do you really need to use the user ID in the ‘live_socket_id’? If so, care to share why?

Generating the live_socket_id by using the user_id was a design decision out of convenience. Our system has to contain certain permission levels and once a users permissions are (partially) revoked we have to disconnect all LV’s to prevent illicit actions.
So it’s in a way, it was a solution to a somewhat similar problem.

But of course there is a way around that, we’ll just have to disconnect all sessions based on the corresponding tokens.

Thanks for sharing. Sounds like a good plan :+1:t2: