phoenixframework / phoenix_live_dashboard

Realtime dashboard with metrics, request logging, plus storage, OS and VM insights

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Possibility to configure custom on_mount

lauriannala opened this issue · comments

As I understand, currently on phoenix live dashboard the user can be authenticated on the initial http-request and after successful authentication, the live socket connection is established. There are some considerations which could be solved by providing an option to wire up a custom on_mount-hook to phoenix live dashboard:

  • Socket connection lifecycle: when the session has expired, the socket connection has to be terminated
  • Session resource (session user in database for example): if the resource is no longer available or is no longer valid to access dashboard, the socket connection has to be terminated

Related issue:
#321

Hi @lauriannala , there are two ways you can achieve this:

  1. use a plug in your router that is invoked before the live dashboard route, as plugs always have to be executed before mount

  2. use the new live_session router helper in LiveView to specify a mount callback for all Live routes: https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.Router.html#live_session/3

Note for disconnections you can specify a live_socket_id on your session and broadcasting on that topic will disconnect all users: https://hexdocs.pm/phoenix_live_view/security-model.html#disconnecting-all-instances-of-a-live-user

Thanks for the quick reply @josevalim. Broadcasting disconnects seems to be the option for max-level hardening. For example, on dashboard metrics page the socket connection receives data and sends heartbeats without calling the liveview on_mount-hook, this means the socket connection can live longer than the session since on_mount-hook is not called. Broadcasting disconnects can force the client to call mount-callback and thus will terminate socket connection if necessary.

Indeed! I am hoping we have all bases covered here. Is there anything missing?

I think there might be, maybe we can figure out if it is feasible to cover. Let me elaborate on my scenario.

  • We have established a connection for admin user, we have valid session, dashboard page opened and a liveview socket connected
  • Plug or mount-callback is called whenever page is loaded -> session gets validated
  • Monitor page is left open -> session is not validated anymore but socket connection is still open and can receive and send data
  • Now, ideally the socket connection should be closed whenever session is not valid, eg. user is removed from database or session has expired

With broadcasting I think it is possible to close socket connections that are no longer valid. But should there be a way to hook a callback that is called whenever data is transmitted with the socket? Then we can immediately validate the session and force mount-callback if the session is no longer valid.

The broadcast covers the needs for disconnecting any live session. I don't think adding the callback on data transmission is worth it. Plus it means we would need to add code to each individual LiveView callback across all dashboard pages.

Agreed, broadcasting disconnects is a fair solution for this scenario.

use the new live_session router helper in LiveView to specify a mount callback for all Live routes: https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.Router.html#live_session/3

@josevalim calling live_dashboard seems to initiate its own live session, so when I put it inside a secure session, I get an error like this one:

** (RuntimeError) attempting to define live_session :live_dashboard inside :admin.
live_session definitions cannot be nested.

Passing on_mount to live_dashboard seems to be ignored at the moment.

If I understand that right and live_dashboard indeed starts a session under the hood, then it must forward session options passed to it to the underlying session. Basically if it starts a session we must be able to treat it as a session. Example:

live_dashboard "/monitoring", metrics: ..., on_mount: ...

This way there would be no conflict of live dash and the security guide which states "any session validation must happen both in the HTTP request (plug pipeline) and the stateful connection (LiveView mount).".

A PR for customizing the on_mount will be welcome!

Here you go #420