Current section

Files

Jump to
auth_n lib authenticator db_authenticator.ex
Raw

lib/authenticator/db_authenticator.ex

defmodule AuthN.Authenticator.DBAuthenticator do
@doc ~S"""
Authenticates a user's credentials against a given repository and schema.
The given schema must implement the `AuthN.Ecto.AuthNFields` behaviour, which
allows this function to retrieve the identifier and password schema field names.
Currently, this function assumes the password is hashed using the `Argon2`
function. `Argon2` is recommended over `bcrypt`. See `argon2_elixir` package.
Returns the tuple `{:ok, user}` in case of successful authentication (where user
is the struct fetched from the data store that aligns with the given credentials),
`{:error, :unknown_user}` in case the given identifier is not found in the data
store, and `{:error, :wrong_password}` in case the given password doesn't match the
one found in the data store.
"""
@spec authenticate(String.t(), String.t(), {atom, atom}) :: {:ok, struct} | {:error, atom}
def authenticate(identifier, password, {repo_module_name, schema_module_name}) do
identifier_field = schema_module_name.get_identifier_field()
password_field = schema_module_name.get_password_field()
user = repo_module_name.get_by(schema_module_name, [{identifier_field, identifier}])
cond do
user == nil ->
Argon2.no_user_verify()
{:error, :unknown_user}
true ->
stored_hashed_password = Map.fetch!(user, password_field)
if Argon2.verify_pass(password, stored_hashed_password) do
{:ok, user}
else
{:error, :wrong_password}
end
end
end
end