View Source AshAuthentication (ash_authentication v4.1.0)

AshAuthentication provides a turn-key authentication solution for folks using Ash.

Usage

This package assumes that you have Ash installed and configured. See the Ash documentation for details.

Once installed you can easily add support for authentication by configuring the AshAuthentication extension on your resource:

defmodule MyApp.Accounts.User do
  use Ash.Resource,
    extensions: [AshAuthentication],
    domain: MyApp.Accounts

  attributes do
    uuid_primary_key :id
    attribute :email, :ci_string, allow_nil?: false
    attribute :hashed_password, :string, allow_nil?: false, sensitive?: true
  end

  authentication do
    strategies do
      password :password do
        identity_field :email
        hashed_password_field :hashed_password
      end
    end
  end

  identities do
    identity :unique_email, [:email]
  end
end

If you plan on providing authentication via the web, then you will need to define a plug using AshAuthentication.Plug which builds a Plug.Router that routes incoming authentication requests to the correct provider and provides callbacks for you to manipulate the conn after success or failure.

If you're using AshAuthentication with Phoenix, then check out ash_authentication_phoenix which provides route helpers, a controller abstraction and LiveView components for easy set up.

Authentication Strategies

Currently supported strategies:

  1. AshAuthentication.Strategy.Password
    • authenticate users against your local database using a unique identity (such as username or email address) and a password.
  2. AshAuthentication.Strategy.OAuth2
  3. AshAuthentication.Strategy.MagicLink
    • authenticate by sending a single-use link to the user.

HTTP client settings

Most of the authentication strategies based on OAuth2 wrap the assent package.

If you needs to customize the behavior of the http client used by assent, define a custom http_adapter in the application settings:

config :ash_authentication, :http_adapter, {Assent.HTTPAdapter.Finch, supervisor: MyApp.CustomFinch}

See assent's documentation for more details on the supported http clients and their configuration.

Add-ons

Add-ons are like strategies, except that they don't actually provide authentication - they just provide features adjacent to authentication. Current add-ons:

  1. AshAuthentication.AddOn.Confirmation
    • allows you to force the user to confirm changes using a confirmation token (eg. sending a confirmation email when a new user registers).

Supervisor

Some add-ons or strategies may require processes to be started which manage their state over the lifetime of the application (eg periodically deleting expired token revocations). Because of this you should add {AshAuthentication.Supervisor, otp_app: :my_app} to your application's supervision tree. See the Elixir docs for more information.

Summary

Functions

Find all resources which support authentication for a given OTP application.

Given a subject string, attempt to retrieve a user record.

Return a subject string for user.

Types

@type resource_config() :: %{
  domain: module(),
  providers: [module()],
  resource: module(),
  subject_name: atom()
}
@type subject() :: String.t()

Functions

Link to this function

authenticated_resources(otp_app)

View Source
@spec authenticated_resources(atom() | [atom()]) :: [Ash.Resource.t()]

Find all resources which support authentication for a given OTP application.

Returns a list of resource modules.

Example

iex> authenticated_resources(:ash_authentication)
[Example.User, Example.UserWithTokenRequired]
Link to this macro

authentication(body)

View Source (macro)
Link to this function

do_subject_to_user(subject, resource, options)

View Source
Link to this function

subject_to_user(subject, resource, options \\ [])

View Source
@spec subject_to_user(subject() | URI.t(), Ash.Resource.t(), keyword()) ::
  {:ok, Ash.Resource.record()} | {:error, any()}

Given a subject string, attempt to retrieve a user record.

iex> %{id: user_id} = build_user()
...> {:ok, %{id: ^user_id}} = subject_to_user("user?id=#{user_id}", Example.User)

Any options passed will be passed to the underlying Domain.read/2 callback.

@spec user_to_subject(Ash.Resource.record()) :: subject()

Return a subject string for user.

This is done by concatenating the resource's subject name with the resource's primary key field(s) to generate a uri-like string.

Example:

iex> build_user(id: "ce7969f9-afa5-474c-bc52-ac23a103cef6") |> user_to_subject()
"user?id=ce7969f9-afa5-474c-bc52-ac23a103cef6"