diff --git a/README.md b/README.md index 6bfbce1..059a6f6 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,79 @@ -# AshAuthentication - -Ash Authentication Logo +![Logo](https://github.com/ash-project/ash/blob/main/logos/cropped-for-header-black-text.png?raw=true#gh-light-mode-only) +![Logo](https://github.com/ash-project/ash/blob/main/logos/cropped-for-header-white-text.png?raw=true#gh-dark-mode-only) ![Elixir CI](https://github.com/team-alembic/ash_authentication/workflows/Elixir%20Library/badge.svg) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Hex version badge](https://img.shields.io/hexpm/v/ash_authentication.svg)](https://hex.pm/packages/ash_authentication) +[![Hexdocs badge](https://img.shields.io/badge/docs-hexdocs-purple)](https://hexdocs.pm/ash_authentication) -AshAuthentication provides drop-in support for user authentication for users of -the [Ash framework](https://ash-hq.org). It is designed to be highly -configurable, with sensible defaults covering the most common use-cases. +# Ash Authentication -## Installation +Welcome! Here you will find everything you need to know to get started with and use Ash Authentication. This documentation is best viewed on [hexdocs](https://hexdocs.pm/ash_authentication). -The package can be installed by adding `ash_authentication` to your list of -dependencies in `mix.exs`: +## About the Documentation -```elixir -def deps do - [ - {:ash_authentication, "~> 4.0.0-rc.6"} - ] -end -``` +[**Tutorials**](#tutorials) walk you through a series of steps to accomplish a goal. These are **learning-oriented**, and are a great place for beginners to start. -## Documentation +--- -See the [official documentation](https://ash-hq.org/docs/guides/ash_authentication/latest/tutorials/getting-started-with-authentication) for more. +[**Topics**](#topics) provide a high level overview of a specific concept or feature. These are **understanding-oriented**, and are perfect for discovering design patterns, features, and tools related to a given topic. -Additionally, documentation for the latest release will be [available on -hexdocs](https://hexdocs.pm/ash_authentication) and for the [`main` -branch](https://team-alembic.github.io/ash_authentication). +--- -## Contributing +[**How-to**](#how-to) guides are **goal-oriented** recipes for accomplishing specific tasks. These are also good to browse to get an idea of how Ash Authentication works and what is possible with it. -- To contribute updates, fixes or new features please fork and open a - pull-request against `main`. -- To regenerate cheat sheets for the DSLs, run `mix spark.cheat_sheets`. For new strategies ensure you've added them to the extensions and documentation groups in `mix.exs`. -- Please use [conventional - commits](https://www.conventionalcommits.org/en/v1.0.0/) - this allows us to - dynamically generate the changelog. -- Feel free to ask any questions on out [GitHub discussions - page](https://github.com/team-alembic/ash_authentication/discussions). +--- -## Licence +[**Reference**](#reference) documentation is produced automatically from our source code. It comes in the form of module documentation and DSL documentation. This documentation is **information-oriented**. Use the sidebar and the search bar to find relevant reference information. -`AshAuthentication` is licensed under the terms of the [MIT -license](https://opensource.org/licenses/MIT). See the [`LICENSE` file in this -repository](https://github.com/team-alembic/ash_authentication/blob/main/LICENSE) -for details. +## Tutorials + +- [Get Started](documentation/tutorials/get-started.md) + +--- + +## Topics + +- [Custom Strategies](documentation/topics/custom-strategy.md) +- [Policies on Authenticated Resources](documentation/topics/policies-on-authentication-resources.md) +- [Testing](documentation/topics/testing.md) +- [Tokens](documentation/topics/tokens.md) +- [Upgrade guides](documentation/topics/upgrading.md) + +--- + +## How To + +- [Authenticate with Auth0](documentation/how-to/auth0.md) +- [Authenticate with GitHub](documentation/how-to/github.md) +- [Authenticate with Google](documentation/how-to/google.md) +- [Authenticate with Magic Links](documentation/how-to/magic-links.md) +- [Confirmation](documentation/how-to/confirmation.md) + +--- + +## Reference + +- [AshAuthentication DSL](documentation/dsls/DSL:-AshAuthentication.md) +- [AshAuthentication.AddOn.Confirmation DSL](documentation/dsls/DSL:-AshAuthentication.AddOn.Confirmation.md) +- [AshAuthentication.Strategy.Auth0](documentation/dsls/DSL:-AshAuthentication.Strategy.Auth0.md) +- [AshAuthentication.Strategy.Github DSL](documentation/dsls/DSL:-AshAuthentication.Strategy.Github.md) +- [AshAuthentication.Strategy.Google DSL](documentation/dsls/DSL:-AshAuthentication.Strategy.Google.md) +- [AshAuthentication.Strategy.MagicLink DSL](documentation/dsls/DSL:-AshAuthentication.Strategy.MagicLink.md) +- [AshAuthentication.Strategy.OAuth2 DSL](documentation/dsls/DSL:-AshAuthentication.Strategy.OAuth2.md) +- [AshAuthentication.Strategy.Oidc DSL](documentation/dsls/DSL:-AshAuthentication.Strategy.Oidc.md) +- [AshAuthentication.Strategy.Password DSL](documentation/dsls/DSL:-AshAuthentication.Strategy.Password.md) +- [AshAuthentication.TokenResource DSL](documentation/dsls/DSL:-AshAuthentication.TokenResource.md) +- [AshAuthentication.UserIdentity DSL](documentation/dsls/DSL:-AshAuthentication.UserIdentity.md) +- For other reference documentation, see the sidebar & search bar + +## Related packages + +- [Ash Framework](https://hexdocs.pm/ash) +- [Ash Authentication Phoenix](https://hexdocs.pm/ash_authentication_phoenix) | Integrates Ash Authentication into your Phoenix application + +--- + +[![Alembic](logos/alembic.png)](https://alembic.com.au) + +Proudly written and maintained by the team at [Alembic](https://alembic.com.au) for the Ash community. diff --git a/documentation/dsls/DSL:-AshAuthentication.Strategy.Auth0.md b/documentation/dsls/DSL:-AshAuthentication.Strategy.Auth0.md index 530a91a..b236084 100644 --- a/documentation/dsls/DSL:-AshAuthentication.Strategy.Auth0.md +++ b/documentation/dsls/DSL:-AshAuthentication.Strategy.Auth0.md @@ -15,8 +15,9 @@ In order to use Auth0 you need to provide the following minimum configuration: - `client_secret` - `site` -See the [Auth0 quickstart guide](/documentation/tutorials/auth0-quickstart.md) -for more information. +## More documentation: +- The [Auth0 Tutorial](/documentation/tutorial/auth0.md). +- The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) @@ -31,8 +32,9 @@ Provides a pre-configured authentication strategy for [Auth0](https://auth0.com/ This strategy is built using the `:oauth2` strategy, and thus provides all the same configuration options should you need them. -For more information see the [Auth0 Quick Start Guide](/documentation/tutorials/auth0-quickstart.md) -in our documentation. +###### More documentation: +- The [Auth0 Tutorial](/documentation/tutorial/auth0.md). +- The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) ###### Strategy defaults: diff --git a/documentation/dsls/DSL:-AshAuthentication.Strategy.Github.md b/documentation/dsls/DSL:-AshAuthentication.Strategy.Github.md index b3b4d3c..ff7f015 100644 --- a/documentation/dsls/DSL:-AshAuthentication.Strategy.Github.md +++ b/documentation/dsls/DSL:-AshAuthentication.Strategy.Github.md @@ -14,8 +14,9 @@ In order to use GitHub you need to provide the following minimum configuration: - `redirect_uri` - `client_secret` -See the [GitHub quickstart guide](/documentation/tutorials/github-quickstart.html) -for more information. +## More documentation: +- The [GitHub Tutorial](/documentation/tutorial/github.md). +- The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) @@ -30,8 +31,9 @@ Provides a pre-configured authentication strategy for [GitHub](https://github.co This strategy is built using the `:oauth2` strategy, and thus provides all the same configuration options should you need them. -For more information see the [Github Quick Start Guide](/documentation/tutorials/github-quickstart.md) -in our documentation. +###### More documentation: +- The [GitHub Tutorial](/documentation/tutorial/github.md). +- The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) ###### Strategy defaults: diff --git a/documentation/dsls/DSL:-AshAuthentication.Strategy.Google.md b/documentation/dsls/DSL:-AshAuthentication.Strategy.Google.md index 47b1014..913da0b 100644 --- a/documentation/dsls/DSL:-AshAuthentication.Strategy.Google.md +++ b/documentation/dsls/DSL:-AshAuthentication.Strategy.Google.md @@ -15,8 +15,10 @@ In order to use Google you need to provide the following minimum configuration: - `client_secret` - `site` -See the [Google OAuth 2.0 Overview](https://developers.google.com/identity/protocols/oauth2) -for Google setup details. +## More documentation: +- The [Google OAuth 2.0 Overview](https://developers.google.com/identity/protocols/oauth2). +- The [Google Tutorial](/documentation/tutorial/google.md) +- The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) @@ -31,8 +33,10 @@ Provides a pre-configured authentication strategy for [Google](https://google.co This strategy is built using the `:oauth2` strategy, and thus provides all the same configuration options should you need them. -See the [Google OAuth 2.0 Overview](https://developers.google.com/identity/protocols/oauth2) -for Google setup details. +#### More documentation: +- The [Google OAuth 2.0 Overview](https://developers.google.com/identity/protocols/oauth2). +- The [Google Tutorial](/documentation/tutorial/google.md) +- The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) ###### Strategy defaults: diff --git a/documentation/dsls/DSL:-AshAuthentication.Strategy.MagicLink.md b/documentation/dsls/DSL:-AshAuthentication.Strategy.MagicLink.md index e68578e..f45e8e0 100644 --- a/documentation/dsls/DSL:-AshAuthentication.Strategy.MagicLink.md +++ b/documentation/dsls/DSL:-AshAuthentication.Strategy.MagicLink.md @@ -95,6 +95,8 @@ Dispatching to plugs directly: ...> signed_in_user.id == user.id true +See the [Magic Link Tutorial](/documentation/tutorial/magic-links.md) for more information. + ## authentication.strategies.magic_link diff --git a/documentation/dsls/DSL:-AshAuthentication.Strategy.Oidc.md b/documentation/dsls/DSL:-AshAuthentication.Strategy.Oidc.md index a90e9bf..e3863ad 100644 --- a/documentation/dsls/DSL:-AshAuthentication.Strategy.Oidc.md +++ b/documentation/dsls/DSL:-AshAuthentication.Strategy.Oidc.md @@ -48,6 +48,9 @@ A random value generator can look like this: AshAuthentication will dynamically generate one for the session if `nonce` is set to `true`. +## More documentation: +- The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) + ## authentication.strategies.oidc @@ -61,6 +64,9 @@ Provides an OpenID Connect authentication strategy. This strategy is built using the `:oauth2` strategy, and thus provides all the same configuration options should you need them. +###### More documentation: +- The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) + diff --git a/documentation/dsls/DSL:-AshAuthentication.Strategy.Password.md b/documentation/dsls/DSL:-AshAuthentication.Strategy.Password.md index 5cfb2ca..81493bd 100644 --- a/documentation/dsls/DSL:-AshAuthentication.Strategy.Password.md +++ b/documentation/dsls/DSL:-AshAuthentication.Strategy.Password.md @@ -104,6 +104,7 @@ password name \\ :password Strategy for authenticating using local resources as the source of truth. + ### Nested DSLs * [resettable](#authentication-strategies-password-resettable) diff --git a/documentation/dsls/DSL:-AshAuthentication.md b/documentation/dsls/DSL:-AshAuthentication.md index d58dab2..e221d06 100644 --- a/documentation/dsls/DSL:-AshAuthentication.md +++ b/documentation/dsls/DSL:-AshAuthentication.md @@ -59,8 +59,14 @@ Currently supported strategies: - 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. + - authenticate using local or remote [OAuth 2.0](https://oauth.net/2/) compatible services. + - also includes: + - `AshAuthentication.Strategy.Auth0` + - `AshAuthentication.Strategy.Github` + - `AshAuthentication.Strategy.Google` + - `AshAuthentication.Strategy.Oidc` +3. `AshAuthentication.Strategy.MagicLink` + - authenticate by sending a single-use link to the user. ## Add-ons diff --git a/documentation/topics/confirmation.md b/documentation/topics/confirmation.md deleted file mode 100644 index 1ede706..0000000 --- a/documentation/topics/confirmation.md +++ /dev/null @@ -1,7 +0,0 @@ -# Confirmation - -## Inhibiting Updates - -Inhibiting updates can be done with `d:AshAuthentication.AddOn.Confirmation.**authentication**.add_ons.confirmation.inhibit_updates?`. - -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. \ No newline at end of file diff --git a/documentation/topics/custom-strategy.md b/documentation/topics/custom-strategy.md index 8d7c74f..c63bd61 100644 --- a/documentation/topics/custom-strategy.md +++ b/documentation/topics/custom-strategy.md @@ -3,6 +3,8 @@ AshAuthentication allows you to bring your own authentication strategy without having to change the Ash Authentication codebase. +> #### Add-on vs Strategy? {:.info} +> > There is functionally no difference between "add ons" and "strategies" other > than where they appear in the DSL. We invented "add ons" because it felt > weird calling "confirmation" an authentication strategy. @@ -93,9 +95,7 @@ here's a brief overview of what each field we've set does: - `target` is the name of the module which defines our entity struct. We've set it to `__MODULE__` which means that we'll have to define the struct on this module. -- `schema` is a keyword list that defines a `NimbleOptions` schema. Spark - provides a number of additional types over the default ones though, so check - out `Spark.OptionsHelpers` for more information. +- `schema` is a keyword list that defines an options schema. See `Spark.Options`. > By default the entity is added to the `authentication / strategy` DSL, however > if you want it in the `authentication / add_ons` DSL instead you can also pass @@ -148,22 +148,9 @@ The Strategy protocol is used to introspect the strategy so that it can seamlessly fit in with the rest of Ash Authentication. Here are the key concepts: -- "phases" - in terms of HTTP, each strategy is likely to have many phases (eg - OAuth 2.0's "request" and "callback" phases). Essentially you need one - phase for each HTTP endpoint you wish to support with your strategy. In our - case we just want one sign in endpoint. -- "actions" - actions are exactly as they sound - Resource actions which can - be executed by the strategy, whether generated by the strategy (as in the - password strategy) or typed in by the user (as in the OAuth 2.0 strategy). - The reason that we wrap the strategy's actions this way is that all the - built-in strategies (and we hope yours too) allow the user to customise the - name of the actions that it uses. At the very least it should probably - append the strategy name to the action. Using `Strategy.action/4` allows us - to refer these by a more generic name rather than via the user-specified one - (eg `:register` vs `:register_with_password`). -- "routes" - `AshAuthentication.Plug` (or `AshAuthentication.Phoenix.Router`) - will generate routes using `Plug.Router` (or `Phoenix.Router`) - the - `routes/1` callback is used to retrieve this information from the strategy. +- "phases" - in terms of HTTP, each strategy is likely to have many phases (eg OAuth 2.0's "request" and "callback" phases). Essentially you need one phase for each HTTP endpoint you wish to support with your strategy. In our case we just want one sign in endpoint. +- "actions" - actions are exactly as they sound - Resource actions which can be executed by the strategy, whether generated by the strategy (as in the password strategy) or typed in by the user (as in the OAuth 2.0 strategy). The reason that we wrap the strategy's actions this way is that all the built-in strategies (and we hope yours too) allow the user to customise the name of the actions that it uses. At the very least it should probably append the strategy name to the action. Using `Strategy.action/4` allows us to refer these by a more generic name rather than via the user-specified one (eg `:register` vs `:register_with_password`). +- "routes" - `AshAuthentication.Plug` (or [`AshAuthentication.Phoenix.Router.html`](`e:ash_authentication_phoenix:AshAuthentication.Phoenix.Router.html`)) will generate routes using `Plug.Router` (or [`Phoenix.Router`](`e:phoenix:Phoenix.Router.html`)) - the `routes/1` callback is used to retrieve this information from the strategy. Given this information, let's implement the strategy. It's quite long, so I'm going to break it up into smaller chunks. diff --git a/documentation/topics/upgrading.md b/documentation/topics/upgrading.md index 9409bc2..bb1001b 100644 --- a/documentation/topics/upgrading.md +++ b/documentation/topics/upgrading.md @@ -1,9 +1,17 @@ # Upgrading +## Upgrading to version 4.0.0 + +Version 4.0.0 of AshAuthentication adds support for Ash 3.0 and in line with [a number of changes in Ash](`e:ash:upgrading-to-3.0.html`) there are some corresponding changes to Ash Authentication: + +- Token generation is enabled by default, meaning that you will have to explicitly set [`authentication.tokens.enabled?`](documentation/dsls/DSL:-AshAuthentication.md#authentication-tokens-enabled?) to `false` if you don't need them. + +- Sign in tokens are enabled by default in the password strategy. What this means is that instead of returning a regular user token on sign-in in the user's metadata, we generate a short-lived token which can be used to actually sign the user in. This is specifically to allow live-view based sign-in UIs to display an authentication error without requiring a page-load. + ## Upgrading to version 3.6.0. As of version 3.6.0 the `TokenResource` extension adds the `subject` attribute -which allows us to more easily match tokens to specific users. This unlocks +which allows us to more easily match tokens to specific users. This unlocks some new use-cases (eg sign out everywhere). This means that you will need to generate new migrations and migrate your @@ -15,9 +23,9 @@ database. > > If you already have tokens stored in your database then the migration will > likely throw a migration error due to the new `NOT NULL` constraint on -> `subject`. If this happens then you can either delete all your tokens or +> `subject`. If this happens then you can either delete all your tokens or > explicitly add the `subject` attribute to your resource with `allow_nil?` set -> to `true`. eg: +> to `true`. eg: > > ```elixir > attributes do diff --git a/documentation/tutorials/auth0-quickstart.md b/documentation/tutorials/auth0.md similarity index 67% rename from documentation/tutorials/auth0-quickstart.md rename to documentation/tutorials/auth0.md index f66db5c..416a9c2 100644 --- a/documentation/tutorials/auth0-quickstart.md +++ b/documentation/tutorials/auth0.md @@ -1,16 +1,8 @@ -# Auth0 Quick Start Guide +# Auth0 Tutorial -This is a _very quick_ tutorial on how to configure your application to use -Auth0 for authentication. +This is a quick tutorial on how to configure your application to use Auth0 for authentication. -Before you start this tutorial, skip the Token resource while following the -[AshAuthenticationPhoenix guide](https://hexdocs.pm/ash_authentication_phoenix/getting-started-with-ash-authentication-phoenix.html)) - -> [!WARNING] -> Make sure that your `ash_postgres` dependency is `~> 1.3.64`. A bug in previous versions prevents the action shown below from working correctly. - -Next, you need to configure an application in [the Auth0 -dashboard](https://manage.auth0.com/) using the following steps: +First, you need to configure an application in [the Auth0 dashboard](https://manage.auth0.com/) using the following steps: 1. Click "Create Application". 2. Set your application name to something that identifies it. You will likely @@ -18,10 +10,8 @@ dashboard](https://manage.auth0.com/) using the following steps: keep that in mind. 3. Select "Regular Web Application" and click "Create". 4. Switch to the "Settings" tab. -5. Copy the "Domain", "Client ID" and "Client Secret" somewhere safe - we'll - need them soon. -6. In the "Allowed Callback URLs" section, add your callback URL. The - callback URL is generated from the following information: +5. Copy the "Domain", "Client ID" and "Client Secret" somewhere safe - we'll need them soon. +6. In the "Allowed Callback URLs" section, add your callback URL. The callback URL is generated from the following information: - The base URL of the application - in development that would be `http://localhost:4000/` but in production will be your application's @@ -59,11 +49,7 @@ defmodule MyApp.Accounts.User do end ``` -Because all the configuration values should be kept secret (ie the -`client_secret`) or are likely to be different for each environment we use the -`AshAuthentication.Secret` behaviour to provide them. In this case we're -delegating to the OTP application environment, however you may want to use a -system environment variable or some other secret store (eg Vault). +Because all the configuration values should be kept secret (ie the `client_secret`) or are likely to be different for each environment we use the `AshAuthentication.Secret` behaviour to provide them. In this case we're delegating to the OTP application environment, however you may want to use a system environment variable or some other secret store (eg Vault). ```elixir defmodule MyApp.Secrets do @@ -97,25 +83,16 @@ end The values for this configuration should be: - `client_id` - the client ID copied from the Auth0 settings page. -- `redirect_uri` - the URL to the generated auth routes in your application - (eg `http://localhost:4000/auth`). +- `redirect_uri` - the URL to the generated auth routes in your application (eg `http://localhost:4000/auth`). - `client_secret` the client secret copied from the Auth0 settings page. -- `base_url` - the "domain" value copied from the Auth0 settings page prefixed - with `https://` (eg `https://dev-yu30yo5y4tg2hg0y.us.auth0.com`). +- `base_url` - the "domain" value copied from the Auth0 settings page prefixed with `https://` (eg `https://dev-yu30yo5y4tg2hg0y.us.auth0.com`). -Lastly, we need to add a register action to your user resource. This is defined -as an upsert so that it can register new users, or update information for -returning users. The default name of the action is `register_with_` followed by -the strategy name. In our case that is `register_with_auth0`. +Lastly, we need to add a register action to your user resource. This is defined as an upsert so that it can register new users, or update information for returning users. The default name of the action is `register_with_` followed by the strategy name. In our case that is `register_with_auth0`. The register action takes two arguments, `user_info` and the `oauth_tokens`. -- `user_info` contains the [`GET /userinfo` response from - Auth0](https://auth0.com/docs/api/authentication#get-user-info) which you - can use to populate your user attributes as needed. -- `oauth_tokens` contains the [`POST /oauth/token` response from - Auth0](https://auth0.com/docs/api/authentication#get-token) - you may want - to store these if you intend to call the Auth0 API on behalf of the user. +- `user_info` contains the [`GET /userinfo` response from Auth0](https://auth0.com/docs/api/authentication#get-user-info) which you can use to populate your user attributes as needed. +- `oauth_tokens` contains the [`POST /oauth/token` response from Auth0](https://auth0.com/docs/api/authentication#get-token) - you may want to store these if you intend to call the Auth0 API on behalf of the user. ```elixir defmodule MyApp.Accounts.User do diff --git a/documentation/tutorials/confirmation.md b/documentation/tutorials/confirmation.md new file mode 100644 index 0000000..c37fe28 --- /dev/null +++ b/documentation/tutorials/confirmation.md @@ -0,0 +1,173 @@ +# Confirmation Tutorial + +This is a quick tutorial on how to configure your application to enable confirmation. + +In this tutorial we'll assume that you have a `User` resource which uses `email` as it's user identifier. We'll show you how to confirm a new user on sign-up and also require them to confirm if they wish to change their email address. + +Here's the user resource we'll be starting with: + +```elixir +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, public?: true, sensitive?: true + attribute :hashed_password, :string, allow_nil?: false, public?: 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 +``` + +## Confirming newly registered users + +First we start by adding the confirmation add-on to your existing authentication DSL: + +```elixir +defmodule MyApp.Accounts.User do + # ... + + authentication do + # ... + + add_ons do + confirmation :confirm_new_user do + monitor_fields [:email] + confirm_on_create? true + confirm_on_update? false + confirm_action_name :confirm_new_user + sender MyApp.NewUserConfirmationSender + end + end + end +end +``` + +Next we will define our "sender" module using `Swoosh`: + +```elixir +defmodule MyApp.NewUserConfirmationSender do + use AshAuthentication.Sender + + def send(user, token, _opts) do + new() + |> to(user.email) + |> from({"MyApp Admin", "support@myapp.inc"}) + |> subject("Confirm your email address") + |> html_body(""" +

+ Hi!
+ + Someone has tried to register a new account at MyApp. + If it was you, then please click the link below to confirm your identity. If you did not initiate this request then please ignore this email. +

+

+ Click here to confirm your account +

+ """) + |> MyApp.Mailer.deliver() + end +end +``` + +Provided you have your authentication routes hooked up either via `AshAuthentication.Plug` or [`AshAuthentication.Phoenix.Router`](`e:ash_authentication_phoenix:AshAuthentication.Phoenix.Router.html`) then the user will be confirmed when the token is submitted. + +## Confirming changes to monitored fields + +You may want to require a user to perform a confirmation when a certain field changes. For example if a user changes their email address we can send them a new confirmation request. + +First, let's start by defining a new confirmation add-on in our resource: + +```elixir +defmodule MyApp.Accounts.User do + # ... + + authentication do + # ... + + add_ons do + confirmation :confirm_change do + monitor_fields [:email] + confirm_on_create? false + confirm_on_update? true + confirm_action_name :confirm_change + sender MyApp.EmailChangeConfirmationSender + end + end + end +end +``` + +> #### Why two confirmation configurations? {: .info} +> +> While you can perform both of these confirmations with a single confirmation add-on, in general the Ash philosophy is to be more explicit. Each confirmation will have it's own URL (based on the name) and tokens for one will not be able to be used for the other. + +Next, let's define our new sender: + +```elixir +defmodule MyApp.NewUserConfirmationSender do + use AshAuthentication.Sender + + def send(user, token, _opts) do + new() + |> to(user.email) + |> from({"MyApp Admin", "support@myapp.inc"}) + |> subject("Confirm your new email address") + |> html_body(""" +

+ Hi!
+ + You recently changed your email address on MyApp. Please confirm it. +

+

+ Click here to confirm your new email address +

+ """) + |> MyApp.Mailer.deliver() + end +end +``` + +> #### Inhibiting changes {: .tip} +> +> Depending on whether you want the user's changes to be applied _before_ or _after_ confirmation, you can enable the [`inhibit_updates?` DSL option](documentation/dsls/DSL:-AshAuthentication.AddOn.Confirmation.md#authentication-add_ons-confirmation-inhibit_updates?). +> +> When this option is enabled, then any potential changes to monitored fields are instead temporarily stored in the [token resource](documentation/dsls/DSL:-AshAuthentication.TokenResource.md) and applied when the confirmation action is run. + +## Customising the confirmation action + +By default Ash Authentication will generate an update action for confirmation automatically (named `:confirm` unless you change it). You can manually implement this action in order to change it's behaviour and AshAuthentication will validate that the required changes are also present. + +For example, here's an implementation of the `:confirm_change` action mentioned above, which adds a custom change that updates a remote CRM system with the user's new address. + +```elixir +defmodule MyApp.Accounts.User do + # ... + + actions do + # ... + + update :confirm_change do + argument :confirm, :string, allow_nil?: false, public?: true + + change AshAuthentication.AddOn.Confirmation.ConfirmChange + change AshAuthentication.GenerateTokenChange + change MyApp.UpdateCrmSystem, only_when_valid?: true + end + end +end +``` diff --git a/documentation/tutorials/getting-started-with-authentication.md b/documentation/tutorials/get-started.md similarity index 99% rename from documentation/tutorials/getting-started-with-authentication.md rename to documentation/tutorials/get-started.md index 0fb3438..c86ccf3 100644 --- a/documentation/tutorials/getting-started-with-authentication.md +++ b/documentation/tutorials/get-started.md @@ -1,4 +1,4 @@ -# Getting started with Ash Authentication +# Get started with Ash Authentication If you haven't already, read [the getting started guide for Ash](https://ash-hq.org/docs/guides/ash/latest/tutorials/get-started.md). This diff --git a/documentation/tutorials/github-quickstart.md b/documentation/tutorials/github.md similarity index 96% rename from documentation/tutorials/github-quickstart.md rename to documentation/tutorials/github.md index 6edd913..44370a0 100644 --- a/documentation/tutorials/github-quickstart.md +++ b/documentation/tutorials/github.md @@ -1,10 +1,8 @@ -# GitHub Quick Start Guide +# GitHub Tutorial -This is a _very quick_ tutorial on how to configure your application to use -GitHub for authentication. +This is a quick tutorial on how to configure your application to use GitHub for authentication. -First you need to configure an application in your [GitHub developer -settings](https://github.com/settings/developers): +First you need to configure an application in your [GitHub developer settings](https://github.com/settings/developers): 1. Click the "New OAuth App" button. 2. Set your application name to something that identifies it. You will likely diff --git a/documentation/tutorials/google-quickstart.md b/documentation/tutorials/google.md similarity index 67% rename from documentation/tutorials/google-quickstart.md rename to documentation/tutorials/google.md index 879bd80..e6004e1 100644 --- a/documentation/tutorials/google-quickstart.md +++ b/documentation/tutorials/google.md @@ -1,6 +1,6 @@ -# Google Quick Start Guide +# Google Tutorial -This is a _very quick_ tutorial on how to configure Google authentication in your application using the default oauth2 strategy in ash. +This is a quick tutorial on how to configure Google authentication. First you'll need a registered application in [Google Cloud](https://console.cloud.google.com/welcome), in order to get your OAuth 2.0 Client credentials. @@ -23,9 +23,9 @@ defmodule MyApp.Accounts.User do authentication do strategies do oauth2 :google do - client_id "123abc..." - redirect_uri {:ok, "123abc..."} - client_secret fn -> {:ok, "123abc..."} end + client_id MyApp.Secrets + redirect_uri MyApp.Secrets + client_secret MyApp.Secrets end base_url MyApp.Secrets end end @@ -53,19 +53,17 @@ defmodule MyApp.Accounts.User do change AshAuthentication.GenerateTokenChange # Required if you have the `identity_resource` configuration enabled. - # change AshAuthentication.Strategy.OAuth2.IdentityChange + change AshAuthentication.Strategy.OAuth2.IdentityChange - change fn changeset, _ctx -> + change fn changeset, _ -> user_info = Ash.Changeset.get_argument(changeset, :user_info) - changeset - |> Ash.Changeset.change_attribute(:google_info, user_info) - # you could upsert custom user attributes from the given google's user_info - # |> Ash.Changeset.change_attribute(:email, user_info["email"]) - # |> Ash.Changeset.change_attribute(:name, user_info["name"]) - # |> Ash.Changeset.change_attribute(:portrait, user_info["picture"]) + + Ash.Changeset.change_attributes(changeset, Map.take(user_info, ["email"])) end end end + # ... + end ``` diff --git a/documentation/tutorials/integrating-ash-authentication-and-phoenix.md b/documentation/tutorials/integrating-ash-authentication-and-phoenix.md deleted file mode 100644 index 2fd4d4c..0000000 --- a/documentation/tutorials/integrating-ash-authentication-and-phoenix.md +++ /dev/null @@ -1,3 +0,0 @@ -# Integrating Ash Authentication and Phoenix - -This guide is now located in the [AshAuthenticationPhoenix documentation](https://hexdocs.pm/ash_authentication_phoenix/getting-started-with-ash-authentication-phoenix.html) \ No newline at end of file diff --git a/documentation/tutorials/magic-links-quickstart.md b/documentation/tutorials/magic-links.md similarity index 97% rename from documentation/tutorials/magic-links-quickstart.md rename to documentation/tutorials/magic-links.md index 63ef7df..77ea69a 100644 --- a/documentation/tutorials/magic-links-quickstart.md +++ b/documentation/tutorials/magic-links.md @@ -1,4 +1,4 @@ -# Magic Links Quick Start Guide +# Magic Links Tutorial This is a quick tutorial to get you up and running on Magic Links. This assumes you've set up `ash_authentication` and [password reset](https://ash-hq.org/docs/guides/ash_authentication_phoenix/latest/tutorials/getting-started-with-ash-authentication-phoenix) in your Phoenix project. @@ -75,4 +75,3 @@ end # ... ``` - diff --git a/lib/ash_authentication.ex b/lib/ash_authentication.ex index c1b8eb1..ac6378f 100644 --- a/lib/ash_authentication.ex +++ b/lib/ash_authentication.ex @@ -58,8 +58,14 @@ defmodule AshAuthentication do - 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. + - authenticate using local or remote [OAuth 2.0](https://oauth.net/2/) compatible services. + - also includes: + - `AshAuthentication.Strategy.Auth0` + - `AshAuthentication.Strategy.Github` + - `AshAuthentication.Strategy.Google` + - `AshAuthentication.Strategy.Oidc` + 3. `AshAuthentication.Strategy.MagicLink` + - authenticate by sending a single-use link to the user. ## Add-ons diff --git a/lib/ash_authentication/add_ons/confirmation/transformer.ex b/lib/ash_authentication/add_ons/confirmation/transformer.ex index 94dd5db..c3d6855 100644 --- a/lib/ash_authentication/add_ons/confirmation/transformer.ex +++ b/lib/ash_authentication/add_ons/confirmation/transformer.ex @@ -117,7 +117,8 @@ defmodule AshAuthentication.AddOn.Confirmation.Transformer do Transformer.build_entity!(Resource.Dsl, [:actions, :update], :argument, name: :confirm, type: Type.String, - allow_nil?: false + allow_nil?: false, + public?: true ) ] diff --git a/lib/ash_authentication/sender.ex b/lib/ash_authentication/sender.ex index d786f08..52960d8 100644 --- a/lib/ash_authentication/sender.ex +++ b/lib/ash_authentication/sender.ex @@ -1,5 +1,5 @@ defmodule AshAuthentication.Sender do - @moduledoc ~S""" + @moduledoc ~S''' A module to implement sending of a token to a user. Allows you to glue sending of instructions to @@ -16,7 +16,7 @@ defmodule AshAuthentication.Sender do ```elixir defmodule MyApp.PasswordResetSender do - use AshAuthentication.PasswordReset.Sender + use AshAuthentication.Sender import Swoosh.Email def send(user, reset_token, _opts) do @@ -24,7 +24,7 @@ defmodule AshAuthentication.Sender do |> to({user.name, user.email}) |> from({"Doc Brown", "emmet@brown.inc"}) |> subject("Password reset instructions") - |> html_body(" + |> html_body("""

Password reset instructions

Hi #{user.name},
@@ -32,10 +32,10 @@ defmodule AshAuthentication.Sender do Someone (maybe you) has requested a password reset for your account. If you did not initiate this request then please ignore this email.

- + Click here to reset - ") + """) |> MyApp.Mailer.deliver() end end @@ -78,7 +78,7 @@ defmodule AshAuthentication.Sender do end end ``` - """ + ''' alias Ash.Resource diff --git a/lib/ash_authentication/strategies/auth0.ex b/lib/ash_authentication/strategies/auth0.ex index 9d5533b..0b710a0 100644 --- a/lib/ash_authentication/strategies/auth0.ex +++ b/lib/ash_authentication/strategies/auth0.ex @@ -14,8 +14,9 @@ defmodule AshAuthentication.Strategy.Auth0 do - `client_secret` - `site` - See the [Auth0 quickstart guide](/documentation/tutorials/auth0-quickstart.md) - for more information. + ## More documentation: + - The [Auth0 Tutorial](/documentation/tutorial/auth0.md). + - The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) """ alias AshAuthentication.Strategy.{Custom, OAuth2} diff --git a/lib/ash_authentication/strategies/auth0/dsl.ex b/lib/ash_authentication/strategies/auth0/dsl.ex index b17de2b..739bda1 100644 --- a/lib/ash_authentication/strategies/auth0/dsl.ex +++ b/lib/ash_authentication/strategies/auth0/dsl.ex @@ -16,8 +16,9 @@ defmodule AshAuthentication.Strategy.Auth0.Dsl do This strategy is built using the `:oauth2` strategy, and thus provides all the same configuration options should you need them. - For more information see the [Auth0 Quick Start Guide](/documentation/tutorials/auth0-quickstart.md) - in our documentation. + #### More documentation: + - The [Auth0 Tutorial](/documentation/tutorial/auth0.md). + - The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) #### Strategy defaults: diff --git a/lib/ash_authentication/strategies/custom.ex b/lib/ash_authentication/strategies/custom.ex index bdf4c41..e8e7231 100644 --- a/lib/ash_authentication/strategies/custom.ex +++ b/lib/ash_authentication/strategies/custom.ex @@ -2,7 +2,7 @@ defmodule AshAuthentication.Strategy.Custom do @moduledoc """ Define your own custom authentication strategy. - See [the Custom Strategies guide](/documentation/topics/custom-strategy.html) + See [the Custom Strategies guide](/documentation/topics/custom-strategy.md) for more information. """ diff --git a/lib/ash_authentication/strategies/github.ex b/lib/ash_authentication/strategies/github.ex index af196b8..c103b8e 100644 --- a/lib/ash_authentication/strategies/github.ex +++ b/lib/ash_authentication/strategies/github.ex @@ -13,8 +13,9 @@ defmodule AshAuthentication.Strategy.Github do - `redirect_uri` - `client_secret` - See the [GitHub quickstart guide](/documentation/tutorials/github-quickstart.html) - for more information. + ## More documentation: + - The [GitHub Tutorial](/documentation/tutorial/github.md). + - The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) """ alias AshAuthentication.Strategy.{Custom, OAuth2} diff --git a/lib/ash_authentication/strategies/github/dsl.ex b/lib/ash_authentication/strategies/github/dsl.ex index b503f5e..15d521f 100644 --- a/lib/ash_authentication/strategies/github/dsl.ex +++ b/lib/ash_authentication/strategies/github/dsl.ex @@ -16,8 +16,9 @@ defmodule AshAuthentication.Strategy.Github.Dsl do This strategy is built using the `:oauth2` strategy, and thus provides all the same configuration options should you need them. - For more information see the [Github Quick Start Guide](/documentation/tutorials/github-quickstart.md) - in our documentation. + #### More documentation: + - The [GitHub Tutorial](/documentation/tutorial/github.md). + - The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) #### Strategy defaults: diff --git a/lib/ash_authentication/strategies/google.ex b/lib/ash_authentication/strategies/google.ex index 3b398ec..ecd6316 100644 --- a/lib/ash_authentication/strategies/google.ex +++ b/lib/ash_authentication/strategies/google.ex @@ -14,8 +14,10 @@ defmodule AshAuthentication.Strategy.Google do - `client_secret` - `site` - See the [Google OAuth 2.0 Overview](https://developers.google.com/identity/protocols/oauth2) - for Google setup details. + ## More documentation: + - The [Google OAuth 2.0 Overview](https://developers.google.com/identity/protocols/oauth2). + - The [Google Tutorial](/documentation/tutorial/google.md) + - The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) """ alias AshAuthentication.Strategy.{Custom, OAuth2} diff --git a/lib/ash_authentication/strategies/google/dsl.ex b/lib/ash_authentication/strategies/google/dsl.ex index dd9f984..498ce89 100644 --- a/lib/ash_authentication/strategies/google/dsl.ex +++ b/lib/ash_authentication/strategies/google/dsl.ex @@ -16,8 +16,10 @@ defmodule AshAuthentication.Strategy.Google.Dsl do This strategy is built using the `:oauth2` strategy, and thus provides all the same configuration options should you need them. - See the [Google OAuth 2.0 Overview](https://developers.google.com/identity/protocols/oauth2) - for Google setup details. + ## More documentation: + - The [Google OAuth 2.0 Overview](https://developers.google.com/identity/protocols/oauth2). + - The [Google Tutorial](/documentation/tutorial/google.md) + - The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) #### Strategy defaults: diff --git a/lib/ash_authentication/strategies/magic_link.ex b/lib/ash_authentication/strategies/magic_link.ex index f1234fa..af9951e 100644 --- a/lib/ash_authentication/strategies/magic_link.ex +++ b/lib/ash_authentication/strategies/magic_link.ex @@ -93,6 +93,8 @@ defmodule AshAuthentication.Strategy.MagicLink do ...> {_conn, {:ok, signed_in_user}} = Plug.Helpers.get_authentication_result(conn) ...> signed_in_user.id == user.id true + + See the [Magic Link Tutorial](/documentation/tutorial/magic-links.md) for more information. """ defstruct identity_field: :username, diff --git a/lib/ash_authentication/strategies/oidc.ex b/lib/ash_authentication/strategies/oidc.ex index 965f5a1..0e1f7a1 100644 --- a/lib/ash_authentication/strategies/oidc.ex +++ b/lib/ash_authentication/strategies/oidc.ex @@ -46,6 +46,9 @@ defmodule AshAuthentication.Strategy.Oidc do AshAuthentication will dynamically generate one for the session if `nonce` is set to `true`. + + ## More documentation: + - The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) """ alias AshAuthentication.Strategy.{Custom, Oidc} diff --git a/lib/ash_authentication/strategies/oidc/dsl.ex b/lib/ash_authentication/strategies/oidc/dsl.ex index 3166c09..7b89317 100644 --- a/lib/ash_authentication/strategies/oidc/dsl.ex +++ b/lib/ash_authentication/strategies/oidc/dsl.ex @@ -17,6 +17,9 @@ defmodule AshAuthentication.Strategy.Oidc.Dsl do This strategy is built using the `:oauth2` strategy, and thus provides all the same configuration options should you need them. + + #### More documentation: + - The [OAuth2 documentation](`AshAuthentication.Strategy.OAuth2`) """, auto_set_fields: [assent_strategy: Assent.Strategy.OIDC, icon: :oidc], schema: patch_schema() diff --git a/lib/ash_authentication/strategies/password/dsl.ex b/lib/ash_authentication/strategies/password/dsl.ex index 1f99f18..043e3cd 100644 --- a/lib/ash_authentication/strategies/password/dsl.ex +++ b/lib/ash_authentication/strategies/password/dsl.ex @@ -13,7 +13,9 @@ defmodule AshAuthentication.Strategy.Password.Dsl do def dsl do %Entity{ name: :password, - describe: "Strategy for authenticating using local resources as the source of truth.", + describe: """ + Strategy for authenticating using local resources as the source of truth. + """, examples: [ """ password :password do diff --git a/logos/alembic.png b/logos/alembic.png new file mode 100644 index 0000000..0be34c4 Binary files /dev/null and b/logos/alembic.png differ diff --git a/logos/alembic.svg b/logos/alembic.svg new file mode 100644 index 0000000..7a1f4d0 --- /dev/null +++ b/logos/alembic.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/logos/ash-auth-logo.png b/logos/ash-auth-logo.png new file mode 100644 index 0000000..2115669 Binary files /dev/null and b/logos/ash-auth-logo.png differ diff --git a/logos/ash-auth-logo.svg b/logos/ash-auth-logo.svg new file mode 100644 index 0000000..d60bff0 --- /dev/null +++ b/logos/ash-auth-logo.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/logos/ash-auth-small-logo.png b/logos/ash-auth-small-logo.png new file mode 100644 index 0000000..6222cef Binary files /dev/null and b/logos/ash-auth-small-logo.png differ diff --git a/mix.exs b/mix.exs index 97b2ad2..f82abf3 100644 --- a/mix.exs +++ b/mix.exs @@ -2,143 +2,32 @@ defmodule AshAuthentication.MixProject do @moduledoc false use Mix.Project + @description """ + Authentication extension for the Ash Framework. + """ + @version "4.0.0-rc.6" def project do [ app: :ash_authentication, version: @version, - description: "User authentication support for Ash", elixir: "~> 1.13", - start_permanent: Mix.env() == :prod, - preferred_cli_env: [ci: :test], - aliases: aliases(), - deps: deps(), - package: package(), - elixirc_paths: elixirc_paths(Mix.env()), consolidate_protocols: Mix.env() == :prod, + start_permanent: Mix.env() == :prod, + elixirc_paths: elixirc_paths(Mix.env()), + package: package(), + deps: deps(), dialyzer: [ plt_add_apps: [:mix, :ex_unit], plt_core_path: "priv/plts", plt_file: {:no_warn, "priv/plts/dialyzer.plt"} ], - docs: [ - main: "readme", - extras: [ - {"README.md", name: "READ ME"}, - "documentation/tutorials/getting-started-with-authentication.md", - "documentation/tutorials/auth0-quickstart.md", - "documentation/tutorials/github-quickstart.md", - "documentation/tutorials/google-quickstart.md", - "documentation/tutorials/integrating-ash-authentication-and-phoenix.md", - "documentation/tutorials/magic-links-quickstart.md", - "documentation/topics/custom-strategy.md", - "documentation/topics/policies-on-authentication-resources.md", - "documentation/topics/testing.md", - "documentation/topics/tokens.md", - "documentation/topics/confirmation.md", - "documentation/topics/upgrading.md", - "documentation/dsls/DSL:-AshAuthentication.md", - "documentation/dsls/DSL:-AshAuthentication.AddOn.Confirmation.md", - "documentation/dsls/DSL:-AshAuthentication.Strategy.Auth0.md", - "documentation/dsls/DSL:-AshAuthentication.Strategy.Github.md", - "documentation/dsls/DSL:-AshAuthentication.Strategy.Google.md", - "documentation/dsls/DSL:-AshAuthentication.Strategy.MagicLink.md", - "documentation/dsls/DSL:-AshAuthentication.Strategy.OAuth2.md", - "documentation/dsls/DSL:-AshAuthentication.Strategy.Oidc.md", - "documentation/dsls/DSL:-AshAuthentication.Strategy.Password.md", - "documentation/dsls/DSL:-AshAuthentication.TokenResource.md", - "documentation/dsls/DSL:-AshAuthentication.UserIdentity.md" - ], - groups_for_extras: [ - Tutorials: ~r'documentation/tutorials', - "How To": ~r'documentation/how_to', - Topics: ~r'documentation/topics', - DSLs: ~r'documentation/dsls' - ], - extra_section: "GUIDES", - formatters: ["html"], - before_closing_head_tag: fn type -> - if type == :html do - """ - - """ - end - end, - filter_modules: ~r/^Elixir.AshAuthentication/, - source_url_pattern: - "https://github.com/team-alembic/ash_authentication/blob/main/%{path}#L%{line}", - nest_modules_by_prefix: [ - AshAuthentication.Strategy, - AshAuthentication.AddOn, - AshAuthentication.Plug, - AshAuthentication.Validations - ], - groups_for_modules: [ - Extensions: [ - AshAuthentication, - AshAuthentication.TokenResource, - AshAuthentication.UserIdentity - ], - Strategies: [ - AshAuthentication.Strategy, - AshAuthentication.Strategy.Auth0, - AshAuthentication.Strategy.Github, - AshAuthentication.Strategy.Google, - AshAuthentication.Strategy.MagicLink, - AshAuthentication.Strategy.OAuth2, - AshAuthentication.Strategy.Password - ], - CustomStrategies: [ - ~r/AshAuthentication.Strategy.Custom/ - ], - "Add ons": [ - AshAuthentication.AddOn.Confirmation - ], - Cryptography: [ - AshAuthentication.HashProvider, - AshAuthentication.BcryptProvider, - AshAuthentication.Jwt - ], - Introspection: [ - AshAuthentication.Info, - AshAuthentication.TokenResource.Info, - AshAuthentication.UserIdentity.Info - ], - Utilities: [ - AshAuthentication.Debug, - AshAuthentication.Secret, - AshAuthentication.Sender, - AshAuthentication.Supervisor, - ~r/.*Actions$/, - AshAuthentication.Strategy.Password.Actions, - AshAuthentication.TokenResource.Expunger - ], - Plugs: [~r/^AshAuthentication\.Plug.*/, AshAuthentication.Strategy.MagicLink.Plug], - "Reusable Components": [ - AshAuthentication.GenerateTokenChange, - AshAuthentication.Strategy.Password.HashPasswordChange, - AshAuthentication.Strategy.Password.PasswordConfirmationValidation, - AshAuthentication.Strategy.Password.PasswordValidation, - AshAuthentication.Checks.AshAuthenticationInteraction, - AshAuthentication.Password.Plug, - ~r/AshAuthentication.Validations/ - ], - Errors: ~r/AshAuthentication.Errors/, - "DSL Transformers": [ - ~r/Transformer/, - ~r/Verifier/ - ] - ] - ] + docs: docs(), + aliases: aliases(), + description: @description, + preferred_cli_env: [ci: :test], + consolidate_protocols: Mix.env() == :prod ] end @@ -170,6 +59,125 @@ defmodule AshAuthentication.MixProject do defp extra_applications(:test), do: [:logger, :bcrypt_elixir] defp extra_applications(_), do: [:logger] + defp docs do + [ + main: "readme", + source_ref: "v#{@version}", + logo: "logos/ash-auth-small-logo.png", + extra_section: ["GUIDES"], + extras: [ + {"README.md", name: "Home"}, + "documentation/tutorials/get-started.md", + "documentation/tutorials/auth0.md", + "documentation/tutorials/github.md", + "documentation/tutorials/google.md", + "documentation/tutorials/magic-links.md", + "documentation/tutorials/confirmation.md", + "documentation/topics/custom-strategy.md", + "documentation/topics/policies-on-authentication-resources.md", + "documentation/topics/testing.md", + "documentation/topics/tokens.md", + "documentation/topics/upgrading.md", + "documentation/dsls/DSL:-AshAuthentication.md", + "documentation/dsls/DSL:-AshAuthentication.AddOn.Confirmation.md", + "documentation/dsls/DSL:-AshAuthentication.Strategy.Auth0.md", + "documentation/dsls/DSL:-AshAuthentication.Strategy.Github.md", + "documentation/dsls/DSL:-AshAuthentication.Strategy.Google.md", + "documentation/dsls/DSL:-AshAuthentication.Strategy.MagicLink.md", + "documentation/dsls/DSL:-AshAuthentication.Strategy.OAuth2.md", + "documentation/dsls/DSL:-AshAuthentication.Strategy.Oidc.md", + "documentation/dsls/DSL:-AshAuthentication.Strategy.Password.md", + "documentation/dsls/DSL:-AshAuthentication.TokenResource.md", + "documentation/dsls/DSL:-AshAuthentication.UserIdentity.md", + "CHANGELOG.md" + ], + groups_for_extras: [ + "Start Here": [ + "documentation/home.md", + "documentation/tutorials/get-started.md" + ], + Tutorials: ~r"documentation/tutorials", + Topics: ~r"documentation/topics", + "How To": ~r"documentation/how-to", + Reference: ~r"documentation/dsls" + ], + skip_undefined_reference_warnings_on: [ + "CHANGELOG.md" + ], + nest_modules_by_prefix: [], + before_closing_head_tag: fn type -> + if type == :html do + """ + + """ + end + end, + filter_modules: ~r/^Elixir.AshAuthentication/, + source_url_pattern: + "https://github.com/team-alembic/ash_authentication/blob/main/%{path}#L%{line}", + groups_for_modules: [ + Extensions: [ + AshAuthentication, + AshAuthentication.TokenResource, + AshAuthentication.UserIdentity + ], + Strategies: [ + AshAuthentication.Strategy, + AshAuthentication.AddOn.Confirmation, + AshAuthentication.Strategy.Auth0, + AshAuthentication.Strategy.Custom, + AshAuthentication.Strategy.Github, + AshAuthentication.Strategy.Google, + AshAuthentication.Strategy.MagicLink, + AshAuthentication.Strategy.OAuth2, + AshAuthentication.Strategy.Oidc, + AshAuthentication.Strategy.Password + ], + Cryptography: [ + AshAuthentication.HashProvider, + AshAuthentication.BcryptProvider, + AshAuthentication.Jwt + ], + Introspection: [ + AshAuthentication.Info, + AshAuthentication.TokenResource.Info, + AshAuthentication.UserIdentity.Info + ], + Utilities: [ + AshAuthentication.Debug, + AshAuthentication.Secret, + AshAuthentication.Sender, + AshAuthentication.Supervisor + ], + Plugs: [ + AshAuthentication.Plug, + AshAuthentication.Plug.Helpers + ], + "Reusable Components": [ + AshAuthentication.GenerateTokenChange, + AshAuthentication.Strategy.Password.HashPasswordChange, + AshAuthentication.Strategy.Password.PasswordConfirmationValidation, + AshAuthentication.Strategy.Password.PasswordValidation, + AshAuthentication.Checks.AshAuthenticationInteraction, + AshAuthentication.Password.Plug, + ~r/AshAuthentication.Validations/ + ], + Errors: [ + ~r/^AshAuthentication\.Errors/ + ], + Internals: ~r/.*/ + ] + ] + end + # Run "mix help deps" to learn about dependencies. defp deps do [