ash_authentication/documentation/dsls/DSL:-AshAuthentication.cheatmd
James Harton 7b607896eb
improvement: Allow all token lifetimes to be specified with a time unit.
Now any DSL option which allows the configuring of a token lifetime
can take _either_ a positive integer in it's previous default unit
or a tuple containing a positive integer and a unit.

Closes #376.

Additionally includes switching the resettable entity to being a singleton since that
feature didn't exist when I started.
2023-09-22 12:15:47 +12:00

298 lines
9.9 KiB
Text

# DSL: AshAuthentication
AshAuthentication provides a turn-key authentication solution for folks using
[Ash](https://www.ash-hq.org/).
## Usage
This package assumes that you have [Ash](https://ash-hq.org/) 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:
```elixir
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`](https://github.com/team-alembic/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`
- authenticate using local or remote [OAuth 2.0](https://oauth.net/2/)
compatible services.
## 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](https://hexdocs.pm/elixir/Application.html#module-the-application-callback-module)
for more information.
<!--- ash-hq-hide-start --> <!--- -->
## DSL Documentation
### Index
* authentication
* tokens
* strategies
* add_ons
### Docs
## authentication
Configure authentication for this resource
* [tokens](#module-tokens)
* [strategies](#module-strategies)
* [add_ons](#module-add_ons)
---
* `:subject_name` (`t: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 (ie `MyApp.Accounts.User` will have a subject
name of `user`).
* `:api` (`t: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` (`t:atom/0`) - The name of the read action used to retrieve records.
Used internally by `AshAuthentication.subject_to_user/2`. If the
action doesn't exist, one will be generated for you. The default value is `:get_by_subject`.
* `:select_for_senders` (list of `t:atom/0`) - A list of fields that we will ensure are selected whenever a sender will be invoked.
This is useful if using something like `ash_graphql` which by default only selects
what fields appear in the query, and if you are exposing these actions that way.
Defaults to `[:email]` if there is an `:email` attribute on the resource, and `[]`
otherwise.
### tokens
Configure JWT settings for this resource
---
* `:enabled?` (`t:boolean/0`) - Should JWTs be generated by this resource? The default value is `false`.
* `:store_all_tokens?` (`t:boolean/0`) - Store all tokens in the `token_resource`?
Some applications need to keep track of all tokens issued to
any user. This is optional behaviour with `ash_authentication`
in order to preserve as much performance as possible. The default value is `false`.
* `:require_token_presence_for_authentication?` (`t: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.
Requires `store_all_tokens?` to be `true`. The default value is `false`.
* `:signing_algorithm` (`t:String.t/0`) - The algorithm to use for token signing.
Available signing algorithms are;
EdDSA, Ed448ph, Ed448, Ed25519ph, Ed25519, PS512, PS384, PS256, ES512, ES384, ES256, RS512, RS384, RS256, HS512, HS384 and HS256. The default value is `"HS256"`.
* `:token_lifetime` - How long a token should be valid.
Since refresh tokens are not yet supported, you should
probably set this to a reasonably long time to ensure
a good user experience.
You can either provide a tuple with a time unit, or a positive
integer, in which case the unit is assumed to be hours.
Defaults to 14 days. The default value is `{14, :days}`.
* `: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 the `AshAuthentication.Secret`
behaviour, a 2 arity anonymous function or a string.
See the module documentation for `AshAuthentication.Secret` for more
information.
### strategies
Configure authentication strategies on this resource
---
### add_ons
Additional add-ons related to, but not providing authentication
---
<!--- ash-hq-hide-stop --> <!--- -->
## authentication
Configure authentication for this resource
### Nested DSLs
* [tokens](#authentication-tokens)
* [strategies](#authentication-strategies)
* [add_ons](#authentication-add_ons)
### Options
| Name | Type | Default | Docs |
| --- | --- | --- | --- |
| `api`* | `module` | | The name of the Ash API to use to access this resource when doing anything authenticaiton related. |
| `subject_name` | `atom` | | 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 (ie `MyApp.Accounts.User` will have a subject name of `user`). |
| `get_by_subject_action_name` | `atom` | `:get_by_subject` | The name of the read action used to retrieve records. Used internally by `AshAuthentication.subject_to_user/2`. If the action doesn't exist, one will be generated for you. |
| `select_for_senders` | `list(atom)` | | A list of fields that we will ensure are selected whenever a sender will be invoked. This is useful if using something like `ash_graphql` which by default only selects what fields appear in the query, and if you are exposing these actions that way. Defaults to `[:email]` if there is an `:email` attribute on the resource, and `[]` otherwise. |
## authentication.tokens
Configure JWT settings for this resource
### Options
| Name | Type | Default | Docs |
| --- | --- | --- | --- |
| `token_resource`* | `module \| false` | | 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. |
| `enabled?` | `boolean` | `false` | Should JWTs be generated by this resource? |
| `store_all_tokens?` | `boolean` | `false` | Store all tokens in the `token_resource`? Some applications need to keep track of all tokens issued to any user. This is optional behaviour with `ash_authentication` in order to preserve as much performance as possible. |
| `require_token_presence_for_authentication?` | `boolean` | `false` | 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. Requires `store_all_tokens?` to be `true`. |
| `signing_algorithm` | `String.t` | `"HS256"` | The algorithm to use for token signing. Available signing algorithms are; EdDSA, Ed448ph, Ed448, Ed25519ph, Ed25519, PS512, PS384, PS256, ES512, ES384, ES256, RS512, RS384, RS256, HS512, HS384 and HS256. |
| `token_lifetime` | `pos_integer \| {pos_integer, :days \| :hours \| :minutes \| :seconds}` | `{14, :days}` | How long a token should be valid. Since refresh tokens are not yet supported, you should probably set this to a reasonably long time to ensure a good user experience. You can either provide a tuple with a time unit, or a positive integer, in which case the unit is assumed to be hours. Defaults to 14 days. |
| `signing_secret` | `(any, any -> any) \| module \| String.t` | | The secret used to sign tokens. Takes either a module which implements the `AshAuthentication.Secret` behaviour, a 2 arity anonymous function or a string. See the module documentation for `AshAuthentication.Secret` for more information. |
## authentication.strategies
Configure authentication strategies on this resource
## authentication.add_ons
Additional add-ons related to, but not providing authentication