[warning] Authentication failed: Query returned no users

🆘 Ash Authentication Policy Issue - SignInPreparation Query Failing I'm having trouble with Ash authentication where sign-in attempts fail with "Query returned no users" even though users exist in the database. The Problem: When I try to sign in through my LiveView: #creating the form defp apply_action(socket, :sign_in, params) do socket |> assign(:form_id, "sign-in-form") |> assign(:action, :sign_in) |> assign(:params, params) |> assign( :form, to_form(Form.for_action(User, :sign_in_with_password, as: "user")) ) # In my SignInLive handle_event: case Form.submit(socket.assigns.form, params: params, read_one?: true, before_submit: &Ash.Changeset.set_context(&1, %{token_type: :sign_in}) ) do {:ok, user} -> # Never reaches here {:error, form} -> # Always hits this with "Query returned no users" end Error Details: Authentication failed: Query returned no users Module: AshAuthentication.Strategy.Password.SignInPreparation action: :sign_in_with_password filter: #Ash.Filter<false> ← The filter is evaluating to false! What I've Confirmed: - User exists in DB: test@test.com with valid bcrypt hash - Direct query works: User |> Ash.read!(authorize?: false) returns the user - Email is :ci_string type and matches database Current User Resource Policies attempting to fix: policies do bypass AshAuthentication.Checks.AshAuthenticationInteraction do authorize_if always() end policy action(:sign_in_with_password) do authorize_if always() end policy action(:sign_in_with_token) do authorize_if always() end policy always() do forbid_if always() end end The Issue: The SignInPreparation can't find users during its internal query, even though the bypass should allow authentication operations. The #Ash.Filter<false> suggests the preparation's user lookup is being blocked by policies.
9 Replies
barnabasj
barnabasj2mo ago
There is a setting to log policy breakdowns https://hexdocs.pm/ash/policies.html#debugging-and-logging ah, I see this is blocking your query
policy always() do
forbid_if always()
end
policy always() do
forbid_if always()
end
all policy blocks that apply need to resolve to authenticated, within a block it goes through the checks until a definitive result is returned
ajst7les
ajst7lesOP2mo ago
Hi thanks for getting back to me I thought that catch all was there for saftey which is why it is auto generated is it safe to remove? Should the auth attempt not be passed by bypass AshAuthentication.Checks.AshAuthenticationInteraction do authorize_if always() end for exmaple if just make it this: policies do bypass AshAuthentication.Checks.AshAuthenticationInteraction do authorize_if always() end end we get this error: [warning] Unhandled error in form submission for MyAppAccounts.User.sign_in_with_password This error was unhandled because Ash.Error.Forbidden.Policy does not implement the AshPhoenix.FormData.Error protocol. ** (Ash.Error.Forbidden.Policy) Bread Crumbs:
Error returned from: MyApp.Accounts.User.sign_in_with_password
forbidden: MyApp.Accounts.User.sign_in_with_password No policy conditions applied to this request. For safety, at least one policy must apply to all requests. unknown actor SAT Solver statement: false and false
barnabasj
barnabasj2mo ago
bypass works differently to other blocks in that only one has to pass to circumvent everything else. but your bypass block doesn't apply, because the context is not set, so it's not seen as a AshAuthentication interaction.
query
|> Ash.Query.set_context(%{
private: %{
ash_authentication?: true
}
})
query
|> Ash.Query.set_context(%{
private: %{
ash_authentication?: true
}
})
This is what happens in AshAuthentication to make the bypass work. you can do the same in your sign in page, if you want to use the bypass
barnabasj
barnabasj2mo ago
btw you can use codeblocks like this to get syntac highlighting
No description
ajst7les
ajst7lesOP2mo ago
thanks for heads up about the syntax highlighting. I guess what mainly getting at this is given I'm using ash pheonix forms to call built in sign in actions why aren't the action auto setting the context? I am calling in theory the same code the defauly sign live view does but simply with my own view
barnabasj
barnabasj2mo ago
yes, it's also the same in the regular AshAuthentication login pages. If it was just on the action level, anyone could call it from anywhere without the policy checks
ajst7les
ajst7lesOP2mo ago
sorry I'm a little confused. Maybe I am missing something. This how I understand it right now: the query being blocked when running sign in with password is in here: AshAuthentication.Strategy.Password.SignInPreparation, this is code that ships with ash, am I expected to edit that and make it set the context? to be clear I'm not calling any custom code here simply trying to submit a form for the sign in with password action
barnabasj
barnabasj2mo ago
no you just need to set the context, when submitting the form like you already do with the before_submit
# In my SignInLive handle_event:
case Form.submit(socket.assigns.form,
params: params,
read_one?: true,
before_submit: &Ash.Query.set_context(&1, %{
token_type: :sign_in,
private: %{
ash_authentication?: true
}
})
) do
{:ok, user} -> # Never reaches here
{:error, form} -> # Always hits this with "Query returned no users"
end
# In my SignInLive handle_event:
case Form.submit(socket.assigns.form,
params: params,
read_one?: true,
before_submit: &Ash.Query.set_context(&1, %{
token_type: :sign_in,
private: %{
ash_authentication?: true
}
})
) do
{:ok, user} -> # Never reaches here
{:error, form} -> # Always hits this with "Query returned no users"
end
ajst7les
ajst7lesOP2mo ago
thanks a lot 🙂

Did you find this page helpful?