lud
Ash authentication on mobile
Hello,
I’m trying out the Ash framework for the first time. I am building an API for a mobile app and I want to implement user authentication.
We are in a first-party app and server configuration, so after reading this I’m wondering if the following could be enough:
- An API endpoint accepting email/password and sending a token
- An API endpoint using Ash Token features
It’s the first time I’m doing a mobile app so I am not sure. But to me it looks like I do not need to implement OAuth2 or OID Connect.
What do you think?
Thanks!
Marked As Solved
zachdaniel
Correct. You’d want to implement the password strategy. That strategy will add all the actions that you need to your resources. I don’t think that a JSON endpoint is created for you for signing in, but if not it is something you should be able to do with a phoenix controller.
use Phoenix.Controller
def sign_in(conn, %{"username" => username, "password" => password}) do
YourUserResource
|> Ash.Query.for_read(:sign_in_with_password, %{username: username, password: password})
|> YourApi.read_one()
|> case do
{:ok, user} ->
conn |> put_status(200) |> json(%{token: user.__metadata__.token})
{:error, error} ->
# handle errors. You should get back an `Ash.Error.Forbidden`
# error with a nested error you can use to provide an error message
end
end
Also Liked
D4no0
Usually if there is mobile involved, there is the google/ios authentication involved. They basically send you a JWT token instead of username/password that you can check for validity against their public certificates.
zachdaniel
Got a couple things:
The set_actor plug puts the actor in an idiomatic place on the conn. But it doesn’t call Ash.set_actor/1, that is an “opt-in” tool for storing the actor in the process dictionary.
What I would generally suggest (and will be default in Ash 3.0) is to set this in your api:
authorization do
authorize :by_default
end
Then authorization will always be running unless you explicitly pass authorize?: false. Not passing an actor is equivalent to actor: nil, but in the default setup, not passing an actor is equivalent to authorize?: false.
If there is a “current actor” then I’d set it as the actor. If its an authentication action, then you can do things like authorize_unless actor_present() to only allow calling it without an actor. You could also add forbid_if always() to make it so that it can only be called with authorize?: false. That is a good way to make something internal only (because api clients and things like that can’t pass authorize?: false.
zachdaniel
Not that you need to, though. You can pretty easily create an endpoint that calls the sign_in_with_password action and extracts the token.







