Packages
ash_authentication
5.0.0-rc.8
5.0.0-rc.12
5.0.0-rc.11
5.0.0-rc.10
5.0.0-rc.9
5.0.0-rc.8
5.0.0-rc.7
5.0.0-rc.6
5.0.0-rc.5
5.0.0-rc.4
5.0.0-rc.3
5.0.0-rc.2
5.0.0-rc.1
5.0.0-rc.0
4.14.1
4.14.0
4.13.7
4.13.6
4.13.5
4.13.4
4.13.3
4.13.2
retired
4.13.1
retired
4.13.0
4.12.0
4.11.0
4.10.0
4.9.9
4.9.8
4.9.7
4.9.6
4.9.5
4.9.4
4.9.3
4.9.2
4.9.1
4.9.0
4.8.7
4.8.6
4.8.5
4.8.3
4.8.2
4.8.1
4.8.0
4.7.6
4.7.5
4.7.4
4.7.3
4.7.2
4.7.1
4.7.0
4.6.4
4.6.3
4.6.2
4.6.1
4.6.0
4.5.6
4.5.5
4.5.4
4.5.3
4.5.2
4.5.1
4.5.0
4.4.9
4.4.8
4.4.7
4.4.6
4.4.5
4.4.4
4.4.3
4.4.2
4.4.1
4.4.0
4.3.12
4.3.11
4.3.10
4.3.9
4.3.8
4.3.7
4.3.6
4.3.5
4.3.4
4.3.3
4.3.2
4.3.1
4.3.0
4.2.7
4.2.6
4.2.5
4.2.4
4.2.3
4.2.2
4.2.1
4.2.0
4.1.0
4.0.4
4.0.3
4.0.2
4.0.1
4.0.0
4.0.0-rc.6
4.0.0-rc.5
4.0.0-rc.3
4.0.0-rc.2
4.0.0-rc.1
4.0.0-rc.0
3.12.4
3.12.3
3.12.2
3.12.1
3.12.0
3.11.16
3.11.15
3.11.14
3.11.13
3.11.12
3.11.11
3.11.10
3.11.9
3.11.8
3.11.7
3.11.6
3.11.5
3.11.4
3.11.3
3.11.2
3.11.1
3.11.0
3.10.8
3.10.7
3.10.6
3.10.5
3.10.4
3.10.3
3.10.2
3.10.1
3.10.0
3.9.6
3.9.5
3.9.4
3.9.3
3.9.2
3.9.1
3.9.0
3.8.0
3.7.9
3.7.8
3.7.6
3.7.5
3.7.4
3.7.3
3.7.2
3.7.1
3.7.0
3.6.1
3.6.0
3.5.3
3.5.2
3.5.1
3.5.0
3.3.1
3.3.0
3.2.2
3.2.1
3.2.0
3.1.0
3.0.3
Authentication extension for the Ash Framework.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/ash_authentication/strategies/totp/plug.ex
# SPDX-FileCopyrightText: 2022 Alembic Pty Ltd
#
# SPDX-License-Identifier: MIT
defmodule AshAuthentication.Strategy.Totp.Plug do
@moduledoc """
Plugs for the TOTP strategy.
Handles setup and sign-in for TOTP authentication.
"""
alias AshAuthentication.{Info, Strategy, Strategy.Totp}
alias Plug.Conn
import Ash.PlugHelpers, only: [get_actor: 1, get_tenant: 1, get_context: 1]
import AshAuthentication.Plug.Helpers, only: [store_authentication_result: 2]
@doc "Handle a TOTP setup request"
@spec setup(Conn.t(), Totp.t()) :: Conn.t()
def setup(conn, strategy) do
params = %{user: get_actor(conn)}
opts = opts(conn)
result = Strategy.action(strategy, :setup, params, opts)
store_authentication_result(conn, result)
end
@doc "Handle a TOTP confirm setup request"
@spec confirm_setup(Conn.t(), Totp.t()) :: Conn.t()
def confirm_setup(conn, strategy) do
params = Map.merge(%{user: get_actor(conn)}, subject_params(conn, strategy))
opts = opts(conn)
result = Strategy.action(strategy, :confirm_setup, params, opts)
store_authentication_result(conn, result)
end
@doc "Handle a TOTP sign-in request"
@spec sign_in(Conn.t(), Totp.t()) :: Conn.t()
def sign_in(conn, strategy) do
params = subject_params(conn, strategy)
opts = opts(conn)
result = Strategy.action(strategy, :sign_in, params, opts)
store_authentication_result(conn, result)
end
@doc """
Handle a TOTP verification request for step-up authentication.
This is used when an already-authenticated user needs to verify their TOTP
code to access protected resources. The user is obtained from the connection's
actor (set by authentication middleware).
On success, stores the verification result and marks TOTP as verified in the
user's metadata.
"""
@spec verify(Conn.t(), Totp.t()) :: Conn.t()
def verify(conn, strategy) do
user = get_actor(conn)
params = subject_params(conn, strategy) |> Map.take(["code"]) |> Map.put("user", user)
opts = opts(conn)
result = Strategy.action(strategy, :verify, params, opts)
case result do
{:ok, true} ->
# Verification succeeded - update user metadata and store success
user_with_metadata =
user
|> Ash.Resource.put_metadata(:totp_verified_at, DateTime.utc_now())
store_authentication_result(conn, {:ok, user_with_metadata})
{:ok, false} ->
store_authentication_result(conn, {:error, "Invalid TOTP code"})
error ->
store_authentication_result(conn, error)
end
end
defp subject_params(conn, strategy) do
subject_name =
strategy.resource
|> Info.authentication_subject_name!()
|> to_string()
Map.get(conn.params, subject_name, %{})
end
defp opts(conn) do
[actor: get_actor(conn), tenant: get_tenant(conn), context: get_context(conn)]
|> Enum.reject(&is_nil(elem(&1, 1)))
end
end