Packages
ash_authentication_phoenix
3.0.0-rc.9
3.0.0-rc.9
3.0.0-rc.8
3.0.0-rc.7
3.0.0-rc.6
3.0.0-rc.4
3.0.0-rc.3
3.0.0-rc.2
3.0.0-rc.1
3.0.0-rc.0
2.17.2
2.17.1
2.17.0
2.16.0
2.15.0
2.14.1
2.14.0
2.13.1
2.13.0
2.12.2
2.12.1
2.12.0
2.11.0
2.10.5
2.10.4
2.10.3
2.10.2
2.10.1
2.10.0
2.9.0
2.8.0
2.7.0
2.6.3
2.6.2
2.6.1
2.6.0
2.5.4
2.5.3
2.5.2
2.5.1
2.5.0
2.4.8
2.4.7
2.4.6
2.4.5
2.4.4
2.4.3
2.4.2
2.4.1
2.4.0
2.3.0
2.2.1
2.2.0
2.1.11
2.1.10
2.1.9
2.1.8
2.1.7
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.2
2.0.1
2.0.0
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
1.9.4
1.9.3
1.9.2
1.9.1
1.9.0
1.8.7
1.8.6
1.8.5
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.7.3
1.7.2
1.7.1
1.7.0
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.1
1.3.0
1.2.0
1.1.0
1.0.1
1.0.0
Phoenix integration for Ash Authentication
Current section
Files
Jump to
Current section
Files
lib/ash_authentication_phoenix/live_session/require_webauthn.ex
# SPDX-FileCopyrightText: 2026 Alembic Pty Ltd
#
# SPDX-License-Identifier: MIT
defmodule AshAuthentication.Phoenix.LiveSession.RequireWebAuthn do
@moduledoc """
A LiveView `on_mount` hook that enforces WebAuthn second-factor verification
for live routes.
Mirrors `AshAuthentication.Phoenix.Plug.RequireWebAuthn` for LiveView. With
no current user, falls through. Otherwise:
* If the user has no registered passkeys, redirects to the setup path
(default `"/webauthn-setup"`).
* If the request lacks `:webauthn_verified_at` (or it's older than
`:max_age`), redirects to the verify path (default `"/webauthn-verify"`).
* Otherwise, continues.
## Usage
live_session :secure,
on_mount: [
{AshAuthentication.Phoenix.LiveSession, :default},
{AshAuthentication.Phoenix.LiveSession.RequireWebAuthn, :require_webauthn}
] do
live "/admin", AdminLive
end
Pass options as a tuple to override defaults:
on_mount: [
{AshAuthentication.Phoenix.LiveSession.RequireWebAuthn,
{:require_webauthn, max_age: 300, verify_path: "/step-up"}}
]
## Options
* `:strategy` — WebAuthn strategy name. Defaults to the first WebAuthn
strategy on the user's resource.
* `:setup_path` — defaults to `"/webauthn-setup"`.
* `:verify_path` — defaults to `"/webauthn-verify"`.
* `:max_age` — maximum age (seconds) of `:webauthn_verified_at`.
* `:current_user_assign` — defaults to `:current_user`.
* `:setup_error_message` / `:verify_error_message` — flash text.
"""
import Phoenix.LiveView, only: [put_flash: 3, redirect: 2]
alias AshAuthentication.Phoenix.WebAuthnHelpers
@default_setup_path "/webauthn-setup"
@default_verify_path "/webauthn-verify"
@default_setup_error "Please register a passkey to continue."
@default_verify_error "Please verify your identity with your passkey to continue."
@doc """
LiveView `on_mount/4` callback that requires WebAuthn verification.
Use as `{AshAuthentication.Phoenix.LiveSession.RequireWebAuthn, :require_webauthn}`
or `{module, {:require_webauthn, opts}}`.
"""
def on_mount(:require_webauthn, _params, _session, socket),
do: require_webauthn(socket)
def on_mount({:require_webauthn, opts}, _params, _session, socket) when is_list(opts),
do: require_webauthn(socket, opts)
@doc """
Checks the socket against the WebAuthn requirements and either continues
or redirects.
"""
@spec require_webauthn(Phoenix.LiveView.Socket.t(), keyword()) ::
{:cont, Phoenix.LiveView.Socket.t()} | {:halt, Phoenix.LiveView.Socket.t()}
def require_webauthn(socket, opts \\ []) do
current_user_assign = Keyword.get(opts, :current_user_assign, :current_user)
setup_path = Keyword.get(opts, :setup_path, @default_setup_path)
verify_path = Keyword.get(opts, :verify_path, @default_verify_path)
setup_error = Keyword.get(opts, :setup_error_message, @default_setup_error)
verify_error = Keyword.get(opts, :verify_error_message, @default_verify_error)
max_age = Keyword.get(opts, :max_age)
strategy = Keyword.get(opts, :strategy)
user = socket.assigns[current_user_assign]
cond do
is_nil(user) ->
{:cont, socket}
not WebAuthnHelpers.webauthn_configured?(user, strategy: strategy) ->
{:halt,
socket
|> put_flash(:error, setup_error)
|> redirect(to: setup_path)}
WebAuthnHelpers.webauthn_verified?(socket,
max_age: max_age,
current_user_assign: current_user_assign
) ->
{:cont, socket}
true ->
{:halt,
socket
|> put_flash(:error, verify_error)
|> redirect(to: verify_path)}
end
end
end