RobertoSchneiders

RobertoSchneiders

Unable to get the URI for a LiveView on_mount authorization hook

I’m trying to get a centralized authentication/authorization system working by using the LiveView on_mount hook, not the handle_params.

This app has pages with different levels of authorization:

  • public: can be accessed by anyone, no need to be authenticated
  • require authentication: need authenticated users
  • require a specific user role: only users with specific roles can access (i.e :admin)

The users can live navigate through those pages, so an unauthenticated user may be able to click a button that navigates to a live view where authentication is required. So the objectives are pretty simple:

  • If an unauthenticated user is trying to (live) navigate to a LiveView that requires authentication, we redirect to login.
  • after logging in the user is redirected back to the page he wanted to access in the first place (important bit).
  • if the user is authenticated but not authorized, we just redirect to home and show a flash message.

I have a module that handles the app authorization based on the URI:

MyApp.authorized(user, uri)

My router:

  live_session :default,
    on_mount: [
      {MyAppWeb.UserAuth, :mount_current_user},
      {MyAppWeb.UserAuth, :ensure_authorized}
    ] do
...

How do I get or build the URI in the on_mount stage? I saw several forum posts and GitHub issues talking about using the handle_params instead. However, that creates several issues in my existing live views because the LiveViews on_mount are executing before authentication/authorization is done. Ideally, I would like to only run the LiveView code once authorization is done. I saw we use to have a few routing helpers (live_path) that would allow me to create the URI based on the live view module (socket.view) and params but that doesn’t exist anymore.

  def on_mount(:ensure_authorized, _params, _session, socket) do
    uri =  "" # <- how to get or build the URI at this stage???

    %{assigns: %{current_user: current_user}} = socket

    case Authorization.authorized(current_user, uri) do
      true ->
        socket
        |> Phoenix.Component.assign(:live_url, uri)
        |> cont()

      {:error, :not_authorized} ->
        socket
        |> Phoenix.LiveView.put_flash(:error, "Not Authorized")
        |> Phoenix.LiveView.redirect(to: ~p"/")
        |> halt()

      {:error, :requires_login} ->
        socket
        |> Phoenix.LiveView.put_flash(:error, "You must log in to access this page.")
        |> Phoenix.LiveView.redirect(to: ~p"/users/log_in?#{%{return_to: uri}}")
        |> halt()
    end
  end

First Post!

krasenyp

krasenyp

I’m not sure your idea would work because when you live navigate, the LiveView you’re navigating to doesn’t get mounted, only handle_params gets run.

Where Next?

Popular in Questions Top

New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Other popular topics Top

New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement