
lmendelowski
Ash Framework: A brief detour into LiveView process shenanigans (page 236)
Hello!
I’m neither an Elixir nor Phoenix or Ash expert, but I believe I found misinformation in the A brief detour into LiveView process shenanigans
section in the book. The paragraph describes the authentication process for the LiveView process with Ash.Authentication
as follows:
The page liveviews, such as TunezWeb.Artists.ShowLive, get the current user via an on_mount callback set up in your app’s router with ash_authentication_live_session. This callback will read the authentication token stored in the session, load the correct user record, and store it in socket.assigns.
I believe this information is not correct. According to ash_authentication_live_session
docs:
Generate a live session wherein all subject assigns are copied from the conn into the socket.
Basically, this function copies all assigns from the conn
object. The process of getting user_id
from the session and loading it into conn.current_user
happens in TunezWeb.Router
via plug :load_from_session
for the browser
pipeline. This function comes from AshAuthentication.Plug.Helpers
and is described in the documentation as:
Attempt to retrieve all actors from the connections’ session.
A wrapper around
AshAuthentication.Plug.Helpers.retrieve_from_session/2
with theotp_app
as extracted from the endpoint.
And if we look at mentioned AshAuthentication.Plug.Helpers.retrieve_from_session/2
function:
Attempt to retrieve all users from the connections’ session.
Iterates through all configured authentication resources for
otp_app
and retrieves any users stored in the session, loads them and stores them in the assigns under their subject name (with the prefixcurrent_
).If there is no user present for a resource then the assign is set to
nil
.
PS. Thank you for the book. It’s an excellent resource on Ash Framework!
Most Liked

jamesharton
Hi
As both a technical reviewer for the book and the author of Ash Authentication this section didn’t jump out at me as wrong - mainly, I suspect, because the memory of all the hoops LiveView forces us to jump through have been suppressed as a self-protection measure.
That said, let’s look at the code:
# From lib/ash_authentication_phoenix/live_session.ex
otp_app
|> AshAuthentication.authenticated_resources()
|> Stream.map(&{to_string(Info.authentication_subject_name!(&1)), &1})
|> Enum.reduce(acc, fn {subject_name, resource}, session ->
case Map.fetch(
conn.assigns,
String.to_existing_atom("current_#{subject_name}")
) do
{:ok, user} when is_struct(user, resource) ->
session
|> Map.put(subject_name, AshAuthentication.user_to_subject(user))
|> Map.put("tenant", Ash.PlugHelpers.get_tenant(conn))
|> Map.put("context", Ash.PlugHelpers.get_context(conn))
_ ->
session
|> Map.put("tenant", Ash.PlugHelpers.get_tenant(conn))
|> Map.put("context", Ash.PlugHelpers.get_context(conn))
end
end)
So you’re right that if there is a current_X
assign in the conn then it should be copied into the live session. It also copies what we call the subject (eg user?id=1234
) into the session along with the tenant and any extra context.
I think where the confusion comes from is when working with nested live views the session is passed in, but not any of the assigns. This required us to add AshAuthentication.Phoenix.assign_new_resources/2
which can have the side-effect of loading the assigned users from the database if require_token_presence_for_authentication?
is set to true
.
I guess my answer is “ you’re both right”
Popular Pragmatic Bookshelf topics










Other popular topics









Categories:
Sub Categories:
Popular Portals
- /elixir
- /rust
- /wasm
- /ruby
- /erlang
- /phoenix
- /keyboards
- /rails
- /js
- /python
- /security
- /go
- /swift
- /vim
- /clojure
- /java
- /haskell
- /emacs
- /svelte
- /onivim
- /typescript
- /crystal
- /c-plus-plus
- /tailwind
- /kotlin
- /gleam
- /react
- /flutter
- /elm
- /ocaml
- /ash
- /vscode
- /opensuse
- /centos
- /php
- /deepseek
- /html
- /zig
- /scala
- /debian
- /nixos
- /lisp
- /sublime-text
- /textmate
- /agda
- /react-native
- /kubuntu
- /arch-linux
- /revery
- /ubuntu
- /django
- /spring
- /manjaro
- /diversity
- /nodejs
- /lua
- /c
- /julia
- /slackware
- /markdown