Hello,
I am working on a web app with Phoenix + Liveview.
I have an authenticated live_session in my router.ex
live_session :dashboard, on_mount: [MyappWeb.RouteInfo, MyappWeb.UserLiveAuth, MyappWeb.LiveAdminSidebar] do scope "/dashboard", MyappWeb do pipe_through [:browser, :require_authenticated_user] live "/", WelcomeLive.Index, :index scope "/settings", SettingsLive do live "/account", Account, :edit live "/account/confirm_email/:token", Account, :confirm_email end scope "/users", UserLive do live "/", Index, :index live "/new", Index, :new live "/:id/edit", Index, :edit live "/:id", Show, :show live "/:id/show/edit", Show, :edit end scope "/roles", RoleLive do live "/", Index, :index live "/new", Index, :new live "/:id/edit", Index, :edit live "/:id", Show, :show live "/:id/show/edit", Show, :edit end end end I use the on_mount to handle authentication and authorization as described in this doc page: Security considerations of the LiveView model
Here is my UserLiveAuth on_mount function
def on_mount(:default, _params, %{"user_token" => user_token} = _session, socket) do socket = socket |> assign_new(:current_user, fn -> Accounts.get_user_by_session_token(user_token) end) |> assign_new(:user_return_to, fn -> &Routes.welcome_index_path(&1, :index) end) |> assign_current_user_access_for_routes() cond do !is_user_logged_in(socket) -> { :halt, socket |> put_flash(:error, "You must log in to access this page.") |> redirect(to: Routes.user_session_path(socket, :new)) } !does_user_have_required_capability_for_current_view(socket) -> { :halt, socket |> put_flash(:error, "Your current role does not allow you to access this page.") |> push_redirect(to: socket.assigns.user_return_to.(socket)) } true -> { :cont, assign(socket, :user_return_to, socket.assigns.current_route_info.menu_item.path) } end end Here is what I’m trying to achieve.
When the authenticated user tries to go to a page he is not allowed to visit (2nd cond), I want to redirect him to the :user_return_to which would be the last valid page he was on.
So I tried to store the current page on the :cont case (3rd cond), but I realised that the assigns are not persisted after a live_redirect.
Is it a normal behaviour?
If so, I am not sure of the purpose of assign_new over assign.
Here is what is explained in the security considerations of the LiveView model
[assign_new] is a convenience to avoid fetching the
current_usermultiple times across LiveViews
In my case current_user is fetched everytime I navigate to a new LiveView of the same live session (using live_redirect links).
Is assign_new only useful when the socket connection is established?
How could I do to store the :user_return_to across different LiveViews? Use localStorage?
Thanks in advance for your help.