View Source AshAuthentication (ash_authentication v3.5.2)
AshAuthentication provides a turn-key authentication solution for folks using Ash.
usage
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]
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
api MyApp.Accounts
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
Authentication Strategies
Currently supported strategies:
AshAuthentication.Strategy.Password
- authenticate users against your local database using a unique identity (such as username or email address) and a password.
AshAuthentication.Strategy.OAuth2
- authenticate using local or remote OAuth 2.0 compatible services.
add-ons
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:
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
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.
dsl-documentation
DSL Documentation
index
Index
- authentication
- tokens
- strategies
- password
- resettable
- oauth2
- auth0
- github
- password
- add_ons
- confirmation
docs
Docs
authentication
authentication
Configure authentication for this resource
- tokens
- strategies
- password
- resettable
- oauth2
- auth0
- github
- password
- add_ons
- confirmation
:subject_name
(atom/0
) - The subject name is used anywhere that a short version of your resource name is needed, eg:- generating token claims,
- generating routes,
- form parameter nesting.
This needs to be unique system-wide and if not set will be inferred from the resource name (ieMyApp.Accounts.User
will have a subject name ofuser
).
:api
(atom/0
) - Required. The name of the Ash API to use to access this resource when doing anything authenticaiton related.:get_by_subject_action_name
(atom/0
) - The name of the read action used to retrieve records.
Used internally byAshAuthentication.subject_to_user/2
. If the action doesn't exist, one will be generated for you. The default value is:get_by_subject
.
tokens
tokens
Configure JWT settings for this resource
:enabled?
(boolean/0
) - Should JWTs be generated by this resource? The default value isfalse
.:store_all_tokens?
(boolean/0
) - Store all tokens in thetoken_resource
?
Some applications need to keep track of all tokens issued to any user. This is optional behaviour withash_authentication
in order to preserve as much performance as possible. The default value isfalse
.:require_token_presence_for_authentication?
(boolean/0
) - Require a locally-stored token for authentication?
This inverts the token validation behaviour from requiring that tokens are not revoked to requiring any token presented by a client to be present in the token resource to be considered valid.
Requiresstore_all_tokens?
to betrue
. The default value isfalse
.:signing_algorithm
(String.t/0
) - The algorithm to use for token signing.
Available signing algorithms are; Ed448ph, Ed448, Ed25519ph, Ed25519, PS512, PS384, PS256, ES512, ES384, ES256, RS512, RS384, RS256, HS512, HS384 and HS256. The default value is"HS256"
.:token_lifetime
(pos_integer/0
) - How long a token should be valid, in hours.
Since refresh tokens are not yet supported, you should probably set this to a reasonably long time to ensure a good user experience.
Defaults to 14 days. The default value is336
.:token_resource
- Required. The resource used to store token information.
If token generation is enabled for this resource, we need a place to store information about tokens, such as revocations and in-flight confirmations.:signing_secret
- The secret used to sign tokens.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.
strategies
strategies
Configure authentication strategies on this resource
password
Strategy for authenticating using local resources as the source of truth.
Examples:
password :password do
identity_field :email
hashed_password_field :hashed_password
hash_provider AshAuthentication.BcryptProvider
confirmation_required? true
end
:identity_field
(atom/0
) - The name of the attribute which uniquely identifies the user.
Usually something likeusername
oremail_address
. The default value is:username
.:hashed_password_field
(atom/0
) - The name of the attribute within which to store the user's password once it has been hashed. The default value is:hashed_password
.:hash_provider
(atom/0
) - A module which implements theAshAuthentication.HashProvider
behaviour.
Used to provide cryptographic hashing of passwords. The default value isAshAuthentication.BcryptProvider
.:confirmation_required?
(boolean/0
) - Whether a password confirmation field is required when registering or changing passwords. The default value istrue
.:password_field
(atom/0
) - The name of the argument used to collect the user's password in plaintext when registering, checking or changing passwords. The default value is:password
.:password_confirmation_field
(atom/0
) - The name of the argument used to confirm the user's password in plaintext when registering or changing passwords. The default value is:password_confirmation
.:register_action_name
(atom/0
) - The name to use for the register action.
If not present it will be generated by prepending the strategy name withregister_with_
.:sign_in_action_name
(atom/0
) - The name to use for the sign in action.
If not present it will be generated by prependign the strategy name withsign_in_with_
.
resettable
Configure password reset options for the resource
:token_lifetime
(pos_integer/0
) - How long should the reset token be valid, in hours.
Defaults to 3 days. The default value is72
.:request_password_reset_action_name
(atom/0
) - The name to use for the action which generates a password reset token.
If not present it will be generated by prepending the strategy name withrequest_password_reset_with_
.:password_reset_action_name
(atom/0
) - The name to use for the action which actually resets the user's password.
If not present it will be generated by prepending the strategy name withpassword_reset_with_
.:sender
- Required. How to send the password reset instructions to the user.
Allows you to glue sending of reset instructions to swoosh, ex_twilio or whatever notification system is appropriate for your application.
Accepts a module, module and opts, or a function that takes a record, reset token and options.
SeeAshAuthentication.Sender
for more information.
oauth2
OAuth2 authentication
:client_id
- Required. The OAuth2 client ID.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
client_id fn _, resource -> :my_app |> Application.get_env(resource, []) |> Keyword.fetch(:oauth_client_id) end
:site
- Required. The base URL of the OAuth2 server - including the leading protocol (iehttps://
).
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
site fn _, resource -> :my_app |> Application.get_env(resource, []) |> Keyword.fetch(:oauth_site) end
:auth_method
- The authentication strategy used, optional. If not set, no authentication will be used during the access token request. The value may be one of the following::client_secret_basic
:client_secret_post
:client_secret_jwt
:private_key_jwt
The default value is:client_secret_post
.
:client_secret
- The OAuth2 client secret.
Required if :auth_method is:client_secret_basic
,:client_secret_post
or:client_secret_jwt
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
site fn _, resource -> :my_app |> Application.get_env(resource, []) |> Keyword.fetch(:oauth_site) end
:authorize_url
- Required. The API url to the OAuth2 authorize endpoint.
Relative to the value ofsite
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
authorize_url fn _, _ -> {:ok, "https://exampe.com/authorize"} end
:token_url
- Required. The API url to access the token endpoint.
Relative to the value ofsite
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
token_url fn _, _ -> {:ok, "https://example.com/oauth_token"} end
:user_url
- Required. The API url to access the user endpoint.
Relative to the value ofsite
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
user_url fn _, _ -> {:ok, "https://example.com/userinfo"} end
:private_key
- The private key to use if:auth_method
is:private_key_jwt
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.:redirect_uri
- Required. The callback URI base.
Not the whole URI back to the callback endpoint, but the URI to yourAuthPlug
. We can generate the rest.
Whilst not particularly secret, it seemed prudent to allow this to be configured dynamically so that you can use different URIs for different environments.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.:authorization_params
(keyword/0
) - Any additional parameters to encode in the request phase.
eg:authorization_params scope: "openid profile email"
The default value is[]
.:registration_enabled?
(boolean/0
) - Is registration enabled for this provider?
If this option is enabled, then new users will be able to register for your site when authenticating and not already present.
If not, then only existing users will be able to authenticate. The default value istrue
.:register_action_name
(atom/0
) - The name of the action to use to register a user.
Only needed ifregistration_enabled?
istrue
.
Because we we don't know the response format of the server, you must implement your own registration action of the same name.
See the "Registration and Sign-in" section of the module documentation for more information.
The default is computed from the strategy name eg:register_with_#{name}
.:sign_in_action_name
(atom/0
) - The name of the action to use to sign in an existing user.
Only needed ifregistration_enabled?
isfalse
.
Because we don't know the response format of the server, you must implement your own sign-in action of the same name.
See the "Registration and Sign-in" section of the module documentation for more information.
The default is computed from the strategy name, eg:sign_in_with_#{name}
.:identity_resource
- The resource used to store user identities.
Given that a user can be signed into multiple different authentication providers at once we use theAshAuthentication.UserIdentity
resource to build a mapping between users, providers and that provider's uid.
See the Identities section of the module documentation for more information.
Set tofalse
to disable. The default value isfalse
.:identity_relationship_name
(atom/0
) - Name of the relationship to the provider identities resource The default value is:identities
.:identity_relationship_user_id_attribute
(atom/0
) - The name of the destination (user_id) attribute on your provider identity resource.
The only reason to change this would be if you changed theuser_id_attribute_name
option of the provider identity. The default value is:user_id
.:name
(atom/0
) - Required. Uniquely identifies the strategy.
auth0
Auth0 authentication
:client_id
- Required. The OAuth2 client ID.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
client_id fn _, resource -> :my_app |> Application.get_env(resource, []) |> Keyword.fetch(:oauth_client_id) end
:site
- Required. The base URL of the OAuth2 server - including the leading protocol (iehttps://
).
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
site fn _, resource -> :my_app |> Application.get_env(resource, []) |> Keyword.fetch(:oauth_site) end
:auth_method
- The authentication strategy used, optional. If not set, no authentication will be used during the access token request. The value may be one of the following::client_secret_basic
:client_secret_post
:client_secret_jwt
:private_key_jwt
The default value is:client_secret_post
.
:client_secret
- The OAuth2 client secret.
Required if :auth_method is:client_secret_basic
,:client_secret_post
or:client_secret_jwt
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
site fn _, resource -> :my_app |> Application.get_env(resource, []) |> Keyword.fetch(:oauth_site) end
:authorize_url
- Required. The API url to the OAuth2 authorize endpoint.
Relative to the value ofsite
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
authorize_url fn _, _ -> {:ok, "https://exampe.com/authorize"} end
:token_url
- Required. The API url to access the token endpoint.
Relative to the value ofsite
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
token_url fn _, _ -> {:ok, "https://example.com/oauth_token"} end
:user_url
- Required. The API url to access the user endpoint.
Relative to the value ofsite
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
user_url fn _, _ -> {:ok, "https://example.com/userinfo"} end
:private_key
- The private key to use if:auth_method
is:private_key_jwt
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.:redirect_uri
- Required. The callback URI base.
Not the whole URI back to the callback endpoint, but the URI to yourAuthPlug
. We can generate the rest.
Whilst not particularly secret, it seemed prudent to allow this to be configured dynamically so that you can use different URIs for different environments.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.:authorization_params
(keyword/0
) - Any additional parameters to encode in the request phase.
eg:authorization_params scope: "openid profile email"
The default value is[]
.:registration_enabled?
(boolean/0
) - Is registration enabled for this provider?
If this option is enabled, then new users will be able to register for your site when authenticating and not already present.
If not, then only existing users will be able to authenticate. The default value istrue
.:register_action_name
(atom/0
) - The name of the action to use to register a user.
Only needed ifregistration_enabled?
istrue
.
Because we we don't know the response format of the server, you must implement your own registration action of the same name.
See the "Registration and Sign-in" section of the module documentation for more information.
The default is computed from the strategy name eg:register_with_#{name}
.:sign_in_action_name
(atom/0
) - The name of the action to use to sign in an existing user.
Only needed ifregistration_enabled?
isfalse
.
Because we don't know the response format of the server, you must implement your own sign-in action of the same name.
See the "Registration and Sign-in" section of the module documentation for more information.
The default is computed from the strategy name, eg:sign_in_with_#{name}
.:identity_resource
- The resource used to store user identities.
Given that a user can be signed into multiple different authentication providers at once we use theAshAuthentication.UserIdentity
resource to build a mapping between users, providers and that provider's uid.
See the Identities section of the module documentation for more information.
Set tofalse
to disable. The default value isfalse
.:identity_relationship_name
(atom/0
) - Name of the relationship to the provider identities resource The default value is:identities
.:identity_relationship_user_id_attribute
(atom/0
) - The name of the destination (user_id) attribute on your provider identity resource.
The only reason to change this would be if you changed theuser_id_attribute_name
option of the provider identity. The default value is:user_id
.:name
(atom/0
) - Required. Uniquely identifies the strategy.
github
GitHub authentication
:client_id
- Required. The OAuth2 client ID.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
client_id fn _, resource -> :my_app |> Application.get_env(resource, []) |> Keyword.fetch(:oauth_client_id) end
:site
- Required. The base URL of the OAuth2 server - including the leading protocol (iehttps://
).
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
site fn _, resource -> :my_app |> Application.get_env(resource, []) |> Keyword.fetch(:oauth_site) end
:auth_method
- The authentication strategy used, optional. If not set, no authentication will be used during the access token request. The value may be one of the following::client_secret_basic
:client_secret_post
:client_secret_jwt
:private_key_jwt
The default value is:client_secret_post
.
:client_secret
- The OAuth2 client secret.
Required if :auth_method is:client_secret_basic
,:client_secret_post
or:client_secret_jwt
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
site fn _, resource -> :my_app |> Application.get_env(resource, []) |> Keyword.fetch(:oauth_site) end
:authorize_url
- Required. The API url to the OAuth2 authorize endpoint.
Relative to the value ofsite
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
authorize_url fn _, _ -> {:ok, "https://exampe.com/authorize"} end
:token_url
- Required. The API url to access the token endpoint.
Relative to the value ofsite
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
token_url fn _, _ -> {:ok, "https://example.com/oauth_token"} end
:user_url
- Required. The API url to access the user endpoint.
Relative to the value ofsite
.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.Example:
user_url fn _, _ -> {:ok, "https://example.com/userinfo"} end
:private_key
- The private key to use if:auth_method
is:private_key_jwt
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.:redirect_uri
- Required. The callback URI base.
Not the whole URI back to the callback endpoint, but the URI to yourAuthPlug
. We can generate the rest.
Whilst not particularly secret, it seemed prudent to allow this to be configured dynamically so that you can use different URIs for different environments.
Takes either a module which implements theAshAuthentication.Secret
behaviour, a 2 arity anonymous function or a string.
See the module documentation forAshAuthentication.Secret
for more information.:authorization_params
(keyword/0
) - Any additional parameters to encode in the request phase.
eg:authorization_params scope: "openid profile email"
The default value is[]
.:registration_enabled?
(boolean/0
) - Is registration enabled for this provider?
If this option is enabled, then new users will be able to register for your site when authenticating and not already present.
If not, then only existing users will be able to authenticate. The default value istrue
.:register_action_name
(atom/0
) - The name of the action to use to register a user.
Only needed ifregistration_enabled?
istrue
.
Because we we don't know the response format of the server, you must implement your own registration action of the same name.
See the "Registration and Sign-in" section of the module documentation for more information.
The default is computed from the strategy name eg:register_with_#{name}
.:sign_in_action_name
(atom/0
) - The name of the action to use to sign in an existing user.
Only needed ifregistration_enabled?
isfalse
.
Because we don't know the response format of the server, you must implement your own sign-in action of the same name.
See the "Registration and Sign-in" section of the module documentation for more information.
The default is computed from the strategy name, eg:sign_in_with_#{name}
.:identity_resource
- The resource used to store user identities.
Given that a user can be signed into multiple different authentication providers at once we use theAshAuthentication.UserIdentity
resource to build a mapping between users, providers and that provider's uid.
See the Identities section of the module documentation for more information.
Set tofalse
to disable. The default value isfalse
.:identity_relationship_name
(atom/0
) - Name of the relationship to the provider identities resource The default value is:identities
.:identity_relationship_user_id_attribute
(atom/0
) - The name of the destination (user_id) attribute on your provider identity resource.
The only reason to change this would be if you changed theuser_id_attribute_name
option of the provider identity. The default value is:user_id
.:name
(atom/0
) - Required. Uniquely identifies the strategy.
add_ons
add_ons
Additional add-ons related to, but not providing authentication
confirmation
User confirmation flow
:token_lifetime
(pos_integer/0
) - How long should the confirmation token be valid, in hours.
Defaults to 3 days. The default value is72
.:monitor_fields
(list ofatom/0
) - Required. A list of fields to monitor for changes (eg[:email, :phone_number]
).
The confirmation will only be sent when one of these fields are changed.:confirmed_at_field
(atom/0
) - The name of a field to store the time that the last confirmation took place.
This attribute will be dynamically added to the resource if not already present. The default value is:confirmed_at
.:confirm_on_create?
(boolean/0
) - Generate and send a confirmation token when a new resource is created?
Will only trigger when a create action is executed and one of the monitored fields is being set. The default value istrue
.:confirm_on_update?
(boolean/0
) - Generate and send a confirmation token when a resource is changed?
Will only trigger when an update action is executed and one of the monitored fields is being set. The default value istrue
.:inhibit_updates?
(boolean/0
) - Wait until confirmation is received before actually changing a monitored field?
If a change to a monitored field is detected, then the change is stored in the token resource and the changeset updated to not make the requested change. When the token is confirmed, the change will be applied.
This could be potentially weird for your users, but useful in the case of a user changing their email address or phone number where you want to verify that the new contact details are reachable. The default value istrue
.:sender
- Required. How to send the confirmation instructions to the user.
Allows you to glue sending of confirmation instructions to swoosh, ex_twilio or whatever notification system is appropriate for your application.
Accepts a module, module and opts, or a function that takes a record, reset token and options.
SeeAshAuthentication.Sender
for more information.:confirm_action_name
(atom/0
) - The name of the action to use when performing confirmation.
If this action is not already present on the resource, it will be created for you. The default value is:confirm
.:name
(atom/0
) - Required. Uniquely identifies the add-on.
Link to this section 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.
Link to this section Types
@type subject() :: String.t()
Link to this section Functions
@spec authenticated_resources(atom()) :: [Ash.Resource.t()]
Find all resources which support authentication for a given OTP application.
Returns a list of resource modules.
example
Example
iex> authenticated_resources(:ash_authentication)
[Example.User, Example.UserWithTokenRequired]
@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 Api.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"