### Install Ash Authentication Separately
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
Installs only the `ash_authentication` package first, then installs `ash_authentication_phoenix`. This is useful to see the specific changes introduced by `ash_authentication_phoenix`.
```bash
mix igniter.install ash_authentication
mix igniter.install ash_authentication_phoenix
```
--------------------------------
### Install Ash Authentication Phoenix
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
Installs the `ash_authentication_phoenix` package. If `ash_authentication` is not already installed, this command will also install it.
```bash
mix igniter.install ash_authentication_phoenix
```
--------------------------------
### Install Ash Authentication Extension (CLI)
Source: https://hexdocs.pm/ash_authentication/get-started
Installs the core ash_authentication extension and optionally the phoenix extension using the Mix Igniter tool. This command allows specifying authentication strategies like magic_link and password during installation.
```bash
mix igniter.install ash_authentication --auth-strategy magic_link,password
```
```bash
mix igniter.install ash_authentication_phoenix --auth-strategy magic_link,password
```
--------------------------------
### Phoenix Router Setup with Ash Authentication
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
Configures the Phoenix router to include authentication routes and pipelines using helper macros provided by `ash_authentication_phoenix`. This involves adding specific `use` and `plug` statements, and defining authentication-related routes.
```elixir
defmodule ExampleWeb.Router do
use ExampleWeb, :router
# add these lines -->
use AshAuthentication.Phoenix.Router
import AshAuthentication.Plug.Helpers
# <-- add these lines
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, {ExampleWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
plug :load_from_session # <-------- Add this line
end
pipeline :api do
plug :accepts, ["json"]
# add these lines -->
plug :load_from_bearer
plug :set_actor, :user
# <-- add these lines
end
scope "/", ExampleWeb do
pipe_through :browser
get "/", PageController, :home
# add these lines -->
# Standard controller-backed routes
auth_routes AuthController, Example.Accounts.User, path: "/auth"
sign_out_route AuthController
# Prebuilt LiveViews for signing in, registration, resetting, etc.
# Leave out `register_path` and `reset_path` if you don't want to support
# user registration and/or password resets respectively.
sign_in_route(register_path: "/register", reset_path: "/reset", auth_routes_prefix: "/auth")
reset_route [auth_routes_prefix: "/auth"]
# <-- add these lines
end
...
end
```
--------------------------------
### Start Phoenix Server Command
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
This command starts the Phoenix server, allowing you to access your application at `localhost:4000`. Ensure your application is properly configured before running this command.
```bash
mix phx.server
```
--------------------------------
### Update Formatter Configuration for Ash Authentication
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
Adds `ash_authentication_phoenix` and related dependencies to the `.formatter.exs` file to enable auto-formatting for the project.
```elixir
[
import_deps: [
:ash_authentication_phoenix, # <-------- Add this line
:ash_authentication,
:ash_postgres,
:ash,
:ecto,
:ecto_sql,
:phoenix
],
subdirectories: ["priv/*/migrations"],
plugins: [Spark.Formatter, Phoenix.LiveView.HTMLFormatter],
inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}", "priv/*/seeds.exs"]
]
```
--------------------------------
### Customizing OAuth2 Registration Action
Source: https://hexdocs.pm/ash_authentication/get-started
Example of customizing the 'register' action for the OAuth2 strategy (GitHub example). It includes required changes and logic to extract user data from the OAuth response.
```elixir
# OAuth2 registration
create :register_with_github do
argument :user_info, :map, allow_nil?: false
argument :oauth_tokens, :map, allow_nil?: false, sensitive?: true
# Required for OAuth2:
change AshAuthentication.GenerateTokenChange
change AshAuthentication.Strategy.OAuth2.IdentityChange
# Extract user data from OAuth response:
change fn changeset, _ctx ->
user_info = Ash.Changeset.get_argument(changeset, :user_info)
Ash.Changeset.change_attributes(changeset, Map.take(user_info, ["email", "name"]))
end
end
```
--------------------------------
### Customizing Password Registration Action
Source: https://hexdocs.pm/ash_authentication/get-started
Example of customizing the 'register' action for the password strategy. It includes required changes like generating a token and hashing the password.
```elixir
# Password registration
create :register_with_password do
# Your custom arguments and logic...
# Required for password strategy:
change AshAuthentication.GenerateTokenChange
change AshAuthentication.Strategy.Password.HashPasswordChange
end
```
--------------------------------
### Setup Ash Authentication Token Resource (Elixir)
Source: https://hexdocs.pm/ash_authentication/get-started
Defines the `Token` resource for Ash Authentication, specifying `AshPostgres.DataLayer`, the `AshAuthentication.TokenResource` extension, and policy configurations. It also sets up the associated PostgreSQL table and repository.
```elixir
# lib/my_app/accounts/token.ex
defmodule MyApp.Accounts.Token do
use Ash.Resource,
data_layer: AshPostgres.DataLayer,
extensions: [AshAuthentication.TokenResource],
# If using policies, enable the policy authorizer:
authorizers: [Ash.Policy.Authorizer],
domain: MyApp.Accounts
postgres do
table "tokens"
repo MyApp.Repo
end
policies do
bypass AshAuthentication.Checks.AshAuthenticationInteraction do
authorize_if always()
end
end
end
```
--------------------------------
### Add Example Repo for Multi-Tenant Enabled User
Source: https://hexdocs.pm/ash_authentication/changelog
This improvement provides an example repository demonstrating how to enable and use multi-tenancy with user authentication. This serves as a helpful guide for developers implementing multitenant features.
```elixir
adding example repo for multi tenant enabled user
```
--------------------------------
### Customize Route Helpers in Phoenix
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
Demonstrates how to customize route helpers in Phoenix to integrate AshAuthentication with existing layouts and specify custom route prefixes. This is useful when migrating an existing application.
```elixir
reset_route(layout: {MyAppWeb, :live}, auth_routes_prefix: "/auth")
```
--------------------------------
### Ash Authentication Controller Implementation
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
Defines the `AuthController` for handling authentication callbacks, including successful sign-ins and failures. It uses `AshAuthentication.Phoenix.Controller` to manage session and redirects.
```elixir
defmodule ExampleWeb.AuthController do
use ExampleWeb, :controller
use AshAuthentication.Phoenix.Controller
def success(conn, _activity, user, _token) do
return_to = get_session(conn, :return_to) || ~p"/"
conn
|> delete_session(:return_to)
|> store_in_session(user)
# If your resource has a different name, update the assign name here (i.e :current_admin)
|> assign(:current_user, user)
|> redirect(to: return_to)
end
def failure(conn, _activity, _reason) do
conn
|> put_flash(:error, "Incorrect email or password")
|> redirect(to: ~p"/sign-in")
end
def sign_out(conn, _params) do
return_to = get_session(conn, :return_to) || ~p"/"
conn
|> clear_session(:my_app)
|> redirect(to: return_to)
end
end
```
--------------------------------
### Ash Authentication Plug Setup
Source: https://hexdocs.pm/ash_authentication/get-started
Defines an authentication plug for Phoenix or Plug applications using AshAuthentication.Plug. It handles successful and failed authentication attempts, differentiating between API requests and traditional web responses.
```elixir
# lib/my_app/auth_plug.ex
defmodule MyApp.AuthPlug do
use AshAuthentication.Plug, otp_app: :my_app
def handle_success(conn, _activity, user, token) do
if is_api_request?(conn) do
conn
|> send_resp(200, Jason.encode!(%{
authentication: %{
success: true,
token: token
}
}))
else
conn
|> store_in_session(user)
|> send_resp(200, EEx.eval_string("""
Welcome back <%= @user.email %>
""", user: user))
end
end
def handle_failure(conn, _activity, _reason) do
if is_api_request?(conn) do
conn
|> send_resp(401, Jason.encode!(%{
authentication: %{
success: false
}
}))
else
conn
|> send_resp(401, "
Incorrect email or password
")
end
end
defp is_api_request?(conn), do: "application/json" in get_req_header(conn, "accept")
end
```
--------------------------------
### Elixir Email Delivery and Reset Instructions
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
The `Example.Accounts.Emails` module handles the delivery of emails, specifically the password reset instructions. It includes a `deliver_reset_password_instructions` function that constructs the email content and a private `deliver` function that simulates email sending by logging to the console and using `Example.Mailer.deliver!`. This simulates integration with an email sending library like Swoosh.
```elixir
defmodule Example.Accounts.Emails do
@moduledoc """
Delivers emails.
"""
import Swoosh.Email
def deliver_reset_password_instructions(user, url) do
if !url do
raise "Cannot deliver reset instructions without a url"
end
deliver(user.email, "Reset Your Password", """
If you didn't request this change, please ignore this.
")
end
# For simplicity, this module simply logs messages to the terminal.
# You should replace it by a proper email or notification tool, such as:
#
# * Swoosh - https://hexdocs.pm/swoosh
# * Bamboo - https://hexdocs.pm/bamboo
#
defp deliver(to, subject, body) do
IO.puts("Sending email to #{to} with subject #{subject} and body #{body}")
new()
|> from({"Zach", "zach@ash-hq.org"}) # TODO: Replace with your email
|> to(to_string(to))
|> subject(subject)
|> put_provider_option(:track_links, "None")
|> html_body(body)
|> Example.Mailer.deliver!()
end
end
```
--------------------------------
### Add Ash Authentication Dependency (Mix)
Source: https://hexdocs.pm/ash_authentication/get-started
Adds the ash_authentication Elixir library as a project dependency in the mix.exs file. It also configures the formatter to import the dependency for consistent code formatting.
```elixir
# mix.exs
defp deps() do
[
# ...
{:ash_authentication, "~> 4.0"}
]
end
```
```elixir
# .formatter.exs
[
import_deps: [..., :ash_authentication]
]
```
--------------------------------
### Configure Tailwind CSS for Ash Authentication Phoenix
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
Shows how to modify the `assets/tailwind.config.js` file to include the `ash_authentication_phoenix` dependency. This is necessary for using the default Tailwind-based components without overriding them.
```javascript
// See the Tailwind configuration guide for advanced usage
// https://tailwindcss.com/docs/configuration
const plugin = require("tailwindcss/plugin");
module.exports = {
content: [
"./js/**/*.js",
"../lib/*_web.ex",
"../lib/*_web/**/*.*ex",
"../deps/ash_authentication_phoenix/**/*.*ex", // <-- Add this line
],
theme: {
extend: {
colors: {
brand: "#FD4F00",
},
},
},
plugins: [
require("@tailwindcss/forms"),
plugin(({ addVariant }) =>
addVariant("phx-no-feedback", [
".phx-no-feedback&",
".phx-no-feedback &",
])
),
plugin(({ addVariant }) =>
addVariant("phx-click-loading", [
".phx-click-loading&",
".phx-click-loading &",
])
),
plugin(({ addVariant }) =>
addVariant("phx-submit-loading", [
".phx-submit-loading&",
".phx-submit-loading &",
])
),
plugin(({ addVariant }) =>
addVariant("phx-change-loading", [
".phx-change-loading&",
".phx-change-loading &",
])
),
],
};
```
--------------------------------
### Install Ash Authentication Phoenix Extension
Source: https://hexdocs.pm/ash_authentication/4.9.5/get-started
Installs the ash_authentication_phoenix extension for Phoenix applications. This command should be used in conjunction with or as an alternative to the base `ash_authentication` installation, also specifying authentication strategies.
```bash
mix igniter.install ash_authentication_phoenix --auth-strategy magic_link,password
```
--------------------------------
### Override Mix Routes Alias for Phoenix <= 1.7
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
Overrides the `phx.routes` alias in `mix.exs` to include routes from `ash_authentication_phoenix`. This is specific to Phoenix versions 1.7 and earlier.
```elixir
defp aliases do
[
setup: ["deps.get", "ash.setup", "assets.setup", "assets.build", "run priv/repo/seeds.exs"],
...
"phx.routes": ["phx.routes", "ash_authentication.phoenix.routes"] # <-------- Add this line
]
end
```
--------------------------------
### Install Ash Authentication Extension
Source: https://hexdocs.pm/ash_authentication/4.9.5/get-started
Installs the ash_authentication extension with specified authentication strategies (magic_link, password) using the `mix igniter.install` command. This is a prerequisite for using the authentication features.
```bash
mix igniter.install ash_authentication --auth-strategy magic_link,password
```
--------------------------------
### Integrate daisyUI Overrides in Phoenix Router
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
Illustrates how to use daisyUI-specific overrides for Ash Authentication in Phoenix. Replace `AshAuthentication.Phoenix.Overrides.Default` with `AshAuthentication.Phoenix.Overrides.DaisyUI` in your router configuration.
```elixir
sign_in_route register_path: "/register",
reset_path: "/reset",
auth_routes_prefix: "/auth",
on_mount: [{ExampleWeb.LiveUserAuth, :live_no_user}],
overrides: [AshAuthentication.Phoenix.Overrides.DaisyUI]
```
--------------------------------
### Install Ash Authentication Phoenix Extension
Source: https://hexdocs.pm/ash_authentication/4.10.0/get-started
Installs the ash_authentication_phoenix extension, specifically for Phoenix applications. This command also configures authentication strategies.
```bash
mix igniter.install ash_authentication_phoenix --auth-strategy magic_link,password
```
--------------------------------
### Install Ash Authentication (Default)
Source: https://hexdocs.pm/ash_authentication/4.10.0/Mix.Tasks.AshAuthentication
Installs the ash_authentication library with default settings. This command sets up the basic authentication structure for your application.
```bash
mix igniter.install ash_authentication
```
--------------------------------
### Using the Authentication Helper in LiveView Tests
Source: https://hexdocs.pm/ash_authentication/4.10.0/testing
Demonstrates how to use the `register_and_log_in_user` helper function within LiveView tests. It can be invoked in the `setup` block for automatic setup before each test, or called directly within a `test` block if more granular control is needed.
```elixir
defmodule MyAppWeb.MyLiveTest do
use MyAppWeb.ConnCase
setup :register_and_log_in_user
test "some test", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/authenticated-route")
# ...
end
end
```
```elixir
test "some test", context do
%{conn: conn} = register_and_log_in_user(context)
{:ok, lv, _html} = live(conn, ~p"/authenticated-route")
# ...
end
```
--------------------------------
### Phoenix HEEx Template for Navigation Bar with User Auth
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
This HEEx template defines a navigation bar for a Phoenix application. It dynamically displays user email and a sign-out button if a user is logged in, or a sign-in button otherwise. It's designed to be placed in `home.html.heex`.
```heex
Demo
```
--------------------------------
### AshAuthentication Debug Log Example
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
This is an example of a debug log message generated by AshAuthentication when an authentication failure occurs with debug mode enabled. It provides details about the failure, such as 'Query returned no users'.
```log
[timestamp] [warning] Authentication failed: Query returned no users
Details: %AshAuthentication.Errors.AuthenticationFailed{
field: nil,
strategy: %AshAuthentication.Strategy.Password{
confirmation_required?: true,
...
```
--------------------------------
### Enable Dark Theme Support for Header Images with daisyUI
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
Provides the CSS configuration to enable dark theme support for header images when using daisyUI with Ash Authentication. This ensures `dark:hidden` and `dark:block` classes work correctly with daisyUI's theme system.
```css
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
```
--------------------------------
### Elixir Password Reset Email Sender Module
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
This module, `Example.Accounts.User.Senders.SendPasswordResetEmail`, implements the `AshAuthentication.Sender` behaviour to send a password reset email. It takes a user, a token, and additional data to construct and deliver the reset link.
```elixir
defmodule Example.Accounts.User.Senders.SendPasswordResetEmail do
@moduledoc """
Sends a password reset email
"""
use AshAuthentication.Sender
use ExampleWeb, :verified_routes
@impl AshAuthentication.Sender
def send(user, token, _) do
Example.Accounts.Emails.deliver_reset_password_instructions(
user,
url(~p"/password-reset/#{token}")
)
end
end
```
--------------------------------
### Enable AshAuthentication Debugging in Development
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
This configuration snippet enables detailed logging for authentication failures in the development environment. It should be added to `config/dev.exs` and is crucial for debugging authentication issues. Do not enable this in production environments.
```elixir
config :ash_authentication, debug_authentication_failures?: true
```
--------------------------------
### Define Ash Authentication User Resource (Elixir)
Source: https://hexdocs.pm/ash_authentication/get-started
Defines the `User` resource with `AshPostgres.DataLayer` and the `AshAuthentication` extension. It includes attribute definitions, custom actions like `get_by_subject`, token management configuration, and security policies.
```elixir
# lib/my_app/accounts/user.ex
defmodule MyApp.Accounts.User do
use Ash.Resource,
data_layer: AshPostgres.DataLayer,
extensions: [AshAuthentication],
authorizers: [Ash.Policy.Authorizer],
domain: MyApp.Accounts
attributes do
uuid_primary_key :id
end
actions do
defaults [:read]
read :get_by_subject do
description "Get a user by the subject claim in a JWT"
argument :subject, :string, allow_nil?: false
get? true
prepare AshAuthentication.Preparations.FilterBySubject
end
end
authentication do
tokens do
enabled? true
token_resource MyApp.Accounts.Token
store_all_tokens? true
signing_secret fn _, _ ->
# This is a secret key used to sign tokens. See the note below on secrets management
Application.fetch_env(:my_app, :token_signing_secret)
end
end
add_ons do
log_out_everywhere do
apply_on_password_change? true
end
end
end
postgres do
table "users"
repo MyApp.Repo
end
# You can customize this if you wish, but this is a safe default that
# only allows user data to be interacted with via AshAuthentication.
policies do
bypass AshAuthentication.Checks.AshAuthenticationInteraction do
authorize_if always()
end
policy always() do
forbid_if always()
end
end
end
```
--------------------------------
### Install Ash Authentication (Custom)
Source: https://hexdocs.pm/ash_authentication/4.10.0/Mix.Tasks.AshAuthentication
Installs the ash_authentication library with custom settings, including authentication strategies, accounts domain, user resource, and token resource. This allows for tailored authentication flows.
```bash
mix igniter.install ash_authentication --auth-strategy magic_link,password --accounts MyApp.AshAccounts --user MyApp.AshAccounts.User --token MyApp.AshAccounts.Token
```
--------------------------------
### Install Ash Authentication Extension
Source: https://hexdocs.pm/ash_authentication/4.10.0/get-started
Installs the ash_authentication extension using the Igniter mix task. This command configures authentication strategies like magic link and password.
```bash
mix igniter.install ash_authentication --auth-strategy magic_link,password
```
--------------------------------
### Define Ash Authentication Domain (Elixir)
Source: https://hexdocs.pm/ash_authentication/get-started
Defines a custom Ash domain named `MyApp.Accounts` which registers `User` and `Token` resources. This domain is then added to the application's Ash configuration.
```elixir
# lib/my_app/accounts.ex
defmodule MyApp.Accounts do
use Ash.Domain
resources do
resource MyApp.Accounts.User
resource MyApp.Accounts.Token
end
end
```
```elixir
# in config/config.exs
config :my_app, ash_domains: [..., MyApp.Accounts]
```
--------------------------------
### Add AshAuthentication Igniter Installer
Source: https://hexdocs.pm/ash_authentication/changelog
Introduces an installer for the Ash Authentication igniter. This simplifies the setup process for new projects integrating Ash Authentication.
```elixir
Add AshAuthentication igniter installer (#782)
igniter installer for user & user token resources
```
--------------------------------
### Support SQLite in Installer
Source: https://hexdocs.pm/ash_authentication/changelog
This improvement adds support for SQLite in the installer. This expands the range of databases that can be used with the generated authentication setups.
```elixir
support sqlite in the installer
```
--------------------------------
### Respond to `--auth-strategy` Option in Installer
Source: https://hexdocs.pm/ash_authentication/changelog
Enhances the installer to correctly respond to the `--auth-strategy` command-line option, allowing users to specify the desired authentication strategy during installation.
```elixir
respond to `--auth-strategy` option in installer
support `--auth-strategy` option when installing
```
--------------------------------
### Install AshAuthenticationPhoenix (Mix Task)
Source: https://hexdocs.pm/ash_authentication/_phoenix/Mix.Tasks.AshAuthenticationPhoenix
This code snippet demonstrates how to install the AshAuthenticationPhoenix project using a mix task. The installation process can be customized using various options to specify different resource domains for accounts, users, and tokens.
```bash
mix igniter.install ash_authentication_phoenix
```
--------------------------------
### Security Configuration for Authentication Attributes and Actions
Source: https://hexdocs.pm/ash_authentication/get-started
Demonstrates how to mark sensitive data like hashed passwords and registration arguments as sensitive using the `sensitive?: true` option in Ash. It also shows how to set `public?: true` for identity fields needed by authentication UIs.
```elixir
attributes do
# Identity fields - public for authentication UI
attribute :email, :ci_string, allow_nil?: false, public?: true
# Credentials - always sensitive, never public
attribute :hashed_password, :string, allow_nil?: false, sensitive?: true, public?: false
end
actions do
create :register do
# Credential arguments - always sensitive
argument :password, :string, allow_nil?: false, sensitive?: true
argument :password_confirmation, :string, allow_nil?: false, sensitive?: true
end
end
```
--------------------------------
### Configure Ash Postgres Extensions (Elixir)
Source: https://hexdocs.pm/ash_authentication/get-started
Configures the AshPostgres data layer to use specific PostgreSQL extensions, such as 'ash-functions' and 'citext', which are required for certain Ash functionalities.
```elixir
# lib/my_app/repo.ex
defmodule MyApp.Repo do
use AshPostgres.Repo, otp_app: :my_app
def installed_extensions do
["ash-functions", "citext"]
end
end
```
--------------------------------
### Dispatch Magic Link Sign-In Plug (Elixir)
Source: https://hexdocs.pm/ash_authentication/4.9.5/dsl-ashauthentication-strategy-magiclink
This example demonstrates how to directly dispatch to the magic link sign-in plug endpoint. It involves requesting a token, constructing a GET request with the token, and then using `Strategy.plug` for the sign-in action, finally verifying the authentication result.
```elixir
...> {:ok, token} = MagicLink.request_token_for(strategy, user)
...> conn = conn(:get, "/user/magic_link", %{"token" => token})
...> conn = Strategy.plug(strategy, :sign_in, conn)
...> {_conn, {:ok, signed_in_user}} = Plug.Helpers.get_authentication_result(conn)
...> signed_in_user.id == user.id
true
```
--------------------------------
### Setup Token Resource for Authentication
Source: https://hexdocs.pm/ash_authentication/4.10.0/get-started
Defines the MyApp.Accounts.Token resource, which is essential for token-based authentication. It uses AshPostgres, includes AshAuthentication.TokenResource extension, and sets up basic policies.
```elixir
defmodule MyApp.Accounts.Token do
use Ash.Resource,
data_layer: AshPostgres.DataLayer,
extensions: [AshAuthentication.TokenResource],
authorizers: [Ash.Policy.Authorizer],
domain: MyApp.Accounts
postgres do
table "tokens"
repo MyApp.Repo
end
policies do
bypass AshAuthentication.Checks.AshAuthenticationInteraction do
authorize_if always()
end
end
end
```
--------------------------------
### Using the Logged-in User Helper in LiveView Tests (Elixir)
Source: https://hexdocs.pm/ash_authentication/4.9.5/testing
Demonstrates how to use the `register_and_log_in_user` helper within LiveView tests by passing it to the `setup` function. This ensures the test context includes an authenticated user for testing protected routes.
```elixir
defmodule MyAppWeb.MyLiveTest do
use MyAppWeb.ConnCase
setup :register_and_log_in_user
test "some test", %{conn: conn} do
{:ok, lv, _html} = live(conn, ~p"/authenticated-route")
# ...
end
end
```
--------------------------------
### Configure Resettable Password Strategy in User Resource
Source: https://hexdocs.pm/ash_authentication/_phoenix/get-started
This Elixir code snippet configures the `password` strategy for the `User` resource to be resettable. It specifies an email sender for password reset emails. This code should replace the existing `strategies` block in `lib/example/accounts/user.ex`.
```elixir
# [...]
strategies do
password :password do
identity_field :email
resettable do
sender Example.Accounts.User.Senders.SendPasswordResetEmail
end
end
end
```
--------------------------------
### AshAuthentication - Configuration
Source: https://hexdocs.pm/ash_authentication/AshAuthentication
Configuration example for adding AshAuthentication to a resource, including defining authentication strategies and identities.
```APIDOC
## AshAuthentication Resource Configuration
### Description
This section details how to configure a resource to use AshAuthentication, including setting up authentication strategies and identities.
### Method
Configuration (within resource definition)
### Endpoint
N/A
### Parameters
#### Resource Attributes
- **email** (ci_string) - Required - User's email address.
- **hashed_password** (string) - Required, Sensitive - Hashed password for the user.
#### Authentication Strategies
- **password** (:password)
- **identity_field**: (atom) - The field to use for identity (e.g., :email).
- **hashed_password_field**: (atom) - The field storing the hashed password.
#### Identities
- **unique_email**: [:email] - Defines a unique email identity for the user.
### Request Example
```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
attribute :hashed_password, :string, allow_nil?: false, sensitive?: true
end
authentication do
strategies do
password :password do
identity_field :email
hashed_password_field :hashed_password
end
end
end
identities do
identity :unique_email, [:email]
end
end
```
### Response
N/A (This is a configuration example)
```
--------------------------------
### Elixir Example: Requesting and Signing In with Magic Link
Source: https://hexdocs.pm/ash_authentication/4.10.0/dsl-ashauthentication-strategy-magiclink
Demonstrates how to programmatically request a magic link token for a user and then use that token to sign the user in. This involves interacting with the `AshAuthentication.Strategy` module.
```elixir
iex> strategy = Info.strategy!(Example.User, :magic_link)
...> user = build_user()
...> Strategy.action(strategy, :request, %{"username" => user.username})
:ok
...> {:ok, token} = MagicLink.request_token_for(strategy, user)
...> {:ok, signed_in_user} = Strategy.action(strategy, :sign_in, %{"token" => token})
...> signed_in_user.id == user
true
```
--------------------------------
### Enabling User Registration and Customizing Actions
Source: https://hexdocs.pm/ash_authentication/dsl-ashauthentication-strategy-github
This example illustrates how to enable user registration (`registration_enabled?: true`) and specify custom action names for registration (`register_action_name`) and sign-in (`sign_in_action_name`). This allows for tailored user onboarding and authentication flows.
```elixir
authentication :oauth2, MyApp.Accounts.OAuth2, registration_enabled?: true, register_action_name: :create_user, sign_in_action_name: :authenticate_user
```
--------------------------------
### AshAuthentication OAuth2 Strategy Configuration
Source: https://hexdocs.pm/ash_authentication/dsl-ashauthentication-strategy-oauth2
Configuration example for integrating the OAuth2 strategy into an Ash.Resource.
```APIDOC
## Ash.Resource with OAuth2 Strategy
### Description
This example demonstrates how to configure an Ash.Resource to use the `AshAuthentication.Strategy.OAuth2` for user authentication.
### Method
N/A (DSL Configuration)
### Endpoint
N/A (DSL Configuration)
### Parameters
#### Path Parameters
N/A
#### Query Parameters
N/A
#### Request Body
N/A
### Request Example
```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
end
authentication do
strategies do
oauth2 :example do
client_id "OAuth Client ID"
redirect_uri "https://my.app/"
client_secret "My Super Secret Secret"
site "https://auth.example.com/"
end
end
end
end
```
### Response
N/A (DSL Configuration)
#### Success Response (200)
N/A
#### Response Example
N/A
```
--------------------------------
### Setup Options Properly for Ash 3.0
Source: https://hexdocs.pm/ash_authentication/changelog
Ensures that options are set up correctly to be compatible with Ash version 3.0, addressing potential integration issues.
```elixir
setup options properly for ash 3.0 (#785)
```
--------------------------------
### Define Load From Session Plug - Elixir
Source: https://hexdocs.pm/ash_authentication/4.9.5/AshAuthentication.Plug
Generates the `load_from_session/2` plug with the `otp_app` prefilled. This macro simplifies session-based authentication setup within AshAuthentication.
```elixir
define_load_from_session(otp_app)
@spec define_load_from_session(atom()) :: Macro.t()
Generates the `load_from_session/2` plug with the `otp_app` prefilled.
```
--------------------------------
### Customizing Authentication Actions (Elixir)
Source: https://hexdocs.pm/ash_authentication/4.10.0/get-started
Demonstrates how to customize authentication actions like 'register' by adding required changes specific to the strategy. Includes examples for the password and OAuth2 strategies, showing how to define custom arguments and logic.
```elixir
# Password registration
create :register_with_password do
# Your custom arguments and logic...
# Required for password strategy:
change AshAuthentication.GenerateTokenChange
change AshAuthentication.Strategy.Password.HashPasswordChange
end
# OAuth2 registration
create :register_with_github do
argument :user_info, :map, allow_nil?: false
argument :oauth_tokens, :map, allow_nil?: false, sensitive?: true
# Required for OAuth2:
change AshAuthentication.GenerateTokenChange
change AshAuthentication.Strategy.OAuth2.IdentityChange
# Extract user data from OAuth response:
change fn changeset, _ctx ->
user_info = Ash.Changeset.get_argument(changeset, :user_info)
Ash.Changeset.change_attributes(changeset, Map.take(user_info, ["email", "name"]))
end
end
```
--------------------------------
### Elixir Example: Dispatching Magic Link Plugs Directly
Source: https://hexdocs.pm/ash_authentication/4.10.0/dsl-ashauthentication-strategy-magiclink
Illustrates how to directly dispatch to the magic link strategy's plug endpoints for both requesting a link and signing in. This involves manually creating and manipulating a Plug connection.
```elixir
iex> strategy = Info.strategy!(Example.User, :magic_link)
...> user = build_user()
...> conn = conn(:post, "/user/magic_link/request", %{"user" => %{"username" => user.username}})
...> conn = Strategy.plug(strategy, :request, conn)
...> {_conn, {:ok, nil}} = Plug.Helpers.get_authentication_result(conn)
...> {:ok, token} = MagicLink.request_token_for(strategy, user)
...> conn = conn(:get, "/user/magic_link", %{"token" => token})
...> conn = Strategy.plug(strategy, :sign_in, conn)
...> {_conn, {:ok, signed_in_user}} = Plug.Helpers.get_authentication_result(conn)
...> signed_in_user.id == user.id
true
```
--------------------------------
### AshAuthentication.TokenResource Usage
Source: https://hexdocs.pm/ash_authentication/dsl-ashauthentication-tokenresource
Example of how to define a Token resource using AshAuthentication.TokenResource extension.
```APIDOC
## `AshAuthentication.TokenResource` Usage
There is no need to define any attributes or actions (although you can if you want). The extension will wire up everything that's needed for the token system to function.
### Example Usage
```elixir
defmodule MyApp.Accounts.Token do
use Ash.Resource,
data_layer: AshPostgres.DataLayer,
extensions: [AshAuthentication.TokenResource],
domain: MyApp.Accounts
postgres do
table "tokens"
repo MyApp.Repo
end
end
```
Whilst it is possible to have multiple token resources, there is no need to do so.
```
--------------------------------
### Sign In with Magic Link Token (Elixir)
Source: https://hexdocs.pm/ash_authentication/4.9.5/dsl-ashauthentication-strategy-magiclink
This example demonstrates how to sign in a user using a magic link token. It first requests a token using `MagicLink.request_token_for` and then uses `Strategy.action` with the `:sign_in` action and the received token to authenticate the user.
```elixir
...> {:ok, token} = MagicLink.request_token_for(strategy, user)
...> {:ok, signed_in_user} = Strategy.action(strategy, :sign_in, %{"token" => token})
...> signed_in_user.id == user
true
```
--------------------------------
### Ash Authentication Plug Setup (Elixir)
Source: https://hexdocs.pm/ash_authentication/4.10.0/get-started
Defines a custom plug for handling authentication requests in Phoenix or Plug applications. It includes callbacks for successful and failed authentication attempts, distinguishing between API requests (JSON) and standard web requests.
```elixir
# lib/my_app/auth_plug.ex
defmodule MyApp.AuthPlug do
use AshAuthentication.Plug, otp_app: :my_app
def handle_success(conn, _activity, user, token) do
if is_api_request?(conn) do
conn
|> send_resp(200, Jason.encode!(%{
authentication: %{
success: true,
token: token
}
}))
else
conn
|> store_in_session(user)
|> send_resp(200, EEx.eval_string("""
Welcome back <%= @user.email %>
""", user: user))
end
end
def handle_failure(conn, _activity, _reason) do
if is_api_request?(conn) do
conn
|> send_resp(401, Jason.encode!(%{
authentication: %{
success: false
}
}))
else
conn
|> send_resp(401, "
Incorrect email or password
")
end
end
defp is_api_request?(conn), do: "application/json" in get_req_header(conn, "accept")
end
```
--------------------------------
### Customizing Password Registration Action
Source: https://hexdocs.pm/ash_authentication/4.9.5/get-started
Example of customizing the 'register' action for the password strategy. It includes essential changes like token generation and password hashing, along with custom logic if needed.
```elixir
# Password registration
create :register_with_password do
# Your custom arguments and logic...
# Required for password strategy:
change AshAuthentication.GenerateTokenChange
change AshAuthentication.Strategy.Password.HashPasswordChange
end
```
--------------------------------
### Define Strategy Phases and Actions
Source: https://hexdocs.pm/ash_authentication/custom-strategy
Defines the available phases and actions for the authentication strategy. This example specifies a single `:sign_in` phase and action.
```elixir
defimpl AshAuthentication.Strategy, for: OnlyMartiesAtTheParty do
def phases(_), do: [:sign_in]
def actions(_), do: [:sign_in]
end
```
--------------------------------
### Implement Email Confirmation Instructions in Elixir
Source: https://hexdocs.pm/ash_authentication/4.10.0/confirmation
This Elixir module provides a function to deliver email confirmation instructions. It constructs an email with a confirmation link and uses a private `deliver` function to send the email. This example uses `Swoosh.Email` and `MyApp.Mailer` for sending emails.
```elixir
defmodule Example.Accounts.Emails do
@moduledoc """
Delivers emails.
"""
import Swoosh.Email
def deliver_email_confirmation_instructions(user, url) do
if !url do
raise "Cannot deliver confirmation instructions without a url"
end
deliver(user.email, "Confirm your email address", """
Hi #{user.email},
Someone has tried to register a new account using this email address.
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.
""" |
)
end
# For simplicity, this module simply logs messages to the terminal.
# You should replace it by a proper email or notification tool, such as:
#
# * Swoosh - https://hexdocs.pm/swoosh
# * Bamboo - https://hexdocs.pm/bamboo
#
defp deliver(to, subject, body) do
IO.puts("Sending email to #{to} with subject #{subject} and body #{body}")
new()
|> from({"Zach", "zach@ash-hq.org"}) # TODO: Replace with your email
|> to(to_string(to))
|> subject(subject)
|> put_provider_option(:track_links, "None")
|> html_body(body)
|> MyApp.Mailer.deliver!()
end
end
```
--------------------------------
### AshAuthentication OAuth2 Secret Management
Source: https://hexdocs.pm/ash_authentication/dsl-ashauthentication-strategy-oauth2
Examples of how to manage secrets and runtime configuration for the OAuth2 strategy.
```APIDOC
## AshAuthentication OAuth2 Secret Management
### Description
Demonstrates different methods for providing secrets and runtime configuration for the OAuth2 authentication strategy, emphasizing security best practices.
### Method
N/A (DSL Configuration)
### Endpoint
N/A (DSL Configuration)
### Parameters
#### Path Parameters
N/A
#### Query Parameters
N/A
#### Request Body
N/A
### Request Example
**Providing configuration as an anonymous function:**
```elixir
oauth2 do
client_secret fn _path, resource ->
Application.fetch_env(:my_app, resource, :oauth2_client_secret)
end
end
```
**Providing configuration as a module:**
```elixir
defmodule MyApp.Secrets do
use AshAuthentication.Secret
def secret_for([:authentication, :strategies, :example, :client_secret], MyApp.User, _opts), do: Application.fetch_env(:my_app, :oauth2_client_secret)
end
# And in your strategies:
oauth2 :example do
client_secret MyApp.Secrets
end
```
### Response
N/A (DSL Configuration)
#### Success Response (200)
N/A
#### Response Example
N/A
```
--------------------------------
### Ash User Resource with Password Strategy
Source: https://hexdocs.pm/ash_authentication/4.10.0/confirmation
Defines a User resource using Ash with the AshAuthentication extension and a password authentication strategy. It includes basic attributes like email and hashed_password, and an identity for unique emails. This serves as the starting point for the confirmation tutorial.
```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
```