jarlah
How to test live views with ash authentication plugs
I’m trying to find out how to test live views that are protected by Ash Authentication.
A straight forward way is to just fill in username and password and hit submit when visiting a protected page.
In my normal live view code I have this function in my conn_case.ex
def log_in_user(conn, user) do
token = ActivityPlanner.Accounts.generate_user_session_token(user)
conn
|> Phoenix.ConnTest.init_test_session(%{})
|> Plug.Conn.put_session(:user_token, token)
end
But this is using the custom auth stuff generated from gen.auth.
How can make something similar for Ash Authentication ? I think that’s maybe one of the problems with opaque code. Oh and yes I could probably peer into the source code, but currently I’m just whipping out some code and tries to avoid rabbit holes ![]()
the ash project im working on is this GitHub - jarlah/ash-activity-planner · GitHub and the original project I worked on previously with normal live views is this one GitHub - jarlah/activity-planner: An example Phoenix application with foreign key multi tenancy · GitHub
Both of which are hobby projects with sole purpose to grind my way into getting familiar with all of Elixir ![]()
Marked As Solved
jarlah
after a lot of trial and error, and inspecting the connection after login, I saw that a “user” was stored in the session in the form of
"user" => "user?id=ef6f74a3-3795-4f0d-be4f-622db62f8c01"
so I made it all work in the tests by doing this:
setup %{conn: conn} do
user =
AshActivityPlanner.Accounts.User
|> Ash.Changeset.for_create(:register_with_password, %{
email: "test@user.com",
password: "password",
password_confirmation: "password"
})
|> AshActivityPlanner.Accounts.create!()
{:ok, %{conn: log_in_user_as_subject(conn, user)}}
end
# SNIP ...
defp log_in_user_as_subject(conn, user) do
subject = AshAuthentication.user_to_subject(user)
conn
|> Phoenix.ConnTest.init_test_session(%{})
|> Plug.Conn.put_session("user", subject)
end
Also Liked
brunoripa
Hi
!
I have a slightly different implementation for my log_in_user:
strategy = AshAuthentication.Info.strategy!(User, :password)
assert {:ok, %User{} = user} =
AshAuthentication.Strategy.action(strategy, :sign_in, %{
email: email,
password: password
})
conn
|> Phoenix.ConnTest.init_test_session(%{})
|> store_in_session(user)
I am leveraging the strategy so that I will be detecting any change in the resource if any, and also I am using the store_in_session function coming from AshAuthentication.Plug.Helpers, which will protect me from any eventual future change in the api.
Do you see any counterargument for such an implementation ?
Thanks ![]()
zachdaniel
jimsynz
Hi there.
You can rewrite the log_in_user/2 function to use AshAuthentication in a few ways. Here I am assuming that your user resource is called User - if it is something else you will need to change current_user to current_X.
If your application is using retrieve_from_session/2 (possibly via AshAuthentication.Phoenix.Plug.load_from_session/2) and has require_token_presence_for_authentication? set:
def log_in_user(conn, user) do
{:ok, token, _} = AshAuthentication.Jwt.token_for_user(user)
conn
|> Phoenix.ConnTest.init_test_session(%{})
|> Plug.Conn.put_session("current_user_token", token)
end
If your application is using retrieve_from_session/2 and doesn’t have require_token_presence_for_authentication? set:
def log_in_user(conn, user) do
subject = AshAuthentication.user_to_subject(user)
conn
|> Phoenix.ConnTest.init_test_session(%{})
|> Plug.Conn.put_session("current_user", subject)
end
Lastly, if you’re using retrieve_from_bearer/2 (possibly via AshAuthentication.Phoenix.Plug.load_from_bearer/2) you can do:
def log_in_user(conn, user) do
{:ok, token, _} = AshAuthentication.Jwt.token_for_user(user)
conn
|> Plug.Conn.put_req_header("authorization", "Bearer #{token}")
end
All of this information is introspectable via AshAuthentication.Info - so I would welcome a PR that adds some test helpers to AshAuthentication.
Links:
AshAuthentication.Plug.Helpers.retrieve_from_session/2AshAuthentication.Phoenix.Plug.load_from_session/2authentication.tokens.require_token_presence_for_authentication?AshAuthentication.Jwt.token_for_user/3AshAuthentication.user_to_subject/1AshAuthentication.Plug.Helpers.retrieve_from_bearer/2AshAuthentication.Phoenix.Plug.load_from_bearer/2AshAuthentication.Info








