maltoe

maltoe

Passing assigns to LiveView initial render without putting them in the session

Hello :wave: ,

looking for advise on this issue we’re having with LiveView + authentication. We have solutions, only I fear we’re missing something simple and obvious.

Situation: We have an authentication service and an app with a LiveView UI. Incoming requests to the app have already been sent to the auth service before and have received some tokens describing the authentication state (think user id) in the form of custom x- headers.

We’d like to verify them on every request, including of course within our LiveViews (see Security model in the docs). For the normal HTTP request (the initial rendering), we rely on a plug to verify the token, whereas in the websocket-connected LiveView process we use get_connect_info in combination with a x_headers option on the socket. Both work great in terms of authentication. However, we’d also like to be able to pass information from the token to the socket assigns for rendering. This works for the connected?-way with get_connect_info because that happens within an on_mount, yet for the plug-based authentication we’re struggling to find a satisfactory solution.

  • We know about live_session and its session option → That of course allows us to copy assigns from the conn in the initial render into the “LiveView session” which makes them show up in the sessions parameter to on_mount. However, it also causes them to be written to the HTML in the form of an attribute on the LiveView element, and then be sent along the websocket connection when the LiveView registers. We don’t want this behaviour as we don’t want to (needlessly) expose the token information to the client. We also don’t need the “session” to be sent along on the websocket connection anymore (because get_connect_info), all we want is to pass some assigns from the conn (in the initial render request) to the fake “socket” (still in the initial render request) available in on_mount. There has to be a way, right?
  • Idea 1: It would be most amazing if only we could have get_connect_info work on the conn in the initial render… Then we wouldn’t have to pass anything and exclusively authenticate in the on_mount
  • Idea 2: What also would be great would be if someone knew a way to remove entries from the “LiveView session” before rendering the HTML, so could use the session option without exposing anything.

Idea 3, passing the data through the process dictionary of course works fine, but there has to be a different way to achieve this, right? Does anyone have a solution for this that feels “right” in current LiveView best practises?

Thanks a lot in advance!
Best,
malte

related posts / article:

Marked As Solved

wanton7

wanton7

Maybe I didn’t understand your question after all, I thought it was about how to pass authorization information for LiveSocket. So if I now understood correctly your problem was in it’s simplicity, how to pass data from router to LiveView during initial request? There is an example how to do that here in LiveView docs Referencing parent assigns

controller

conn
|> assign(:current_user, user)
|> LiveView.Controller.live_render(MyLive, session: %{“user_id” => user.id})

LiveView mount

def mount(_params, %{“user_id” => user_id}, socket) do
{:ok, assign_new(socket, :current_user, fn → Accounts.get_user!(user_id) end)}
end

There is also previous thread talking about this LiveView lifecycle hook with access to Conn? but the link provided there by José doesn’t work anymore, this is the correct link Security considerations of the LiveView model — Phoenix LiveView v0.17.5

Also Liked

maltoe

maltoe

@wanton7

the assign_new magic does the trick! Genius! Thanks a lot. No idea how I missed this section in the docs so far…

It’s a bit confusing, don’t you think? If you inspect the socket.assigns before calling assign_new, they sure do not contain any assigns from the conn. Only after a call to assign_new they’ll be copied over to the socket.assigns… Odd, but great that it works :tada:

Thanks a lot!

maltoe

maltoe

For others here: For the time being, I went with the process dictionary option. So essentially I have something like

# endpoint
socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [:x_headers]]

# router
plug :remember_x_headers_for_live_view

defp remember_x_headers_for_live_view(conn, _opts) do
  Process.put(:x_headers, my_get_x_headers_func(conn))
end

# on_mount
defp x_headers(socket) do
  if connected?(socket) do
    get_connect_info(socket).x_headers
  else
    Process.get(:x_headers)
  end
end

Feels a bit clumsy, but it works :man_shrugging:

Where Next?

Popular in Questions Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
vac
Hi, I’m quite new in Elixir and I’m trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and I...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New

Other popular topics Top

New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52341 488
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement