I’ve been reading the Phoenix Scopes guide and had a question about how scopes interact with LiveView security. From what I can tell, the scope assigned in on_mount is effectively a snapshot and the current_scope assign doesn’t get refreshed for the lifetime of the WebSocket connection.
If that’s correct, an admin could revoke a user’s organization membership while they have an organization LiveView open. This wouldn’t immediately affect the socket, and subsequent handle_event calls would still carry the original scope with the org attached.
The generated context functions filter by scope (e.g. where: org_id == ^scope.org.id), but that only checks identity, not whether membership is still valid. An “edit org” event fired after revocation would still succeed if the context function trusts the scope.
Is this a real concern or am I misreading how scopes work? And if so, is there a recommended way to handle authorization for LiveViews where permissions can change mid-session?
My approach would be to broadcast a message via PubSub whenever permissions are changed. Then you have a handle_info hook (see attach_hook in the docs) that automatically updates the current_scope assign. Of course you can add any other checks or even redirect away from the LiveView if the permissions don’t allow the user to access it any more.
When you navigate to another liveview you probably run the same on_mount again so depending on your use case that might already be enough.
Also, nothing in phoenix or liveview is “reactive”. If you assign something during an on_mount there isnt some kind of magic dependency tracking going on.
This might seem bothersome but it makes it MUCH simpler to reason about complex systems if they work predictably like this.
If you compare this to a typical SPA like ember.js where you have an authentication service that could change at any time and then, maybe, some reactivity will trigger on the page, but sometimes it won’t because the reactivity gods didn’t bless you. It’s horrible.