Packages
ash_authentication
5.0.0-rc.3
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/recovery_code/plug.ex
# SPDX-FileCopyrightText: 2022 Alembic Pty Ltd
#
# SPDX-License-Identifier: MIT
defmodule AshAuthentication.Strategy.RecoveryCode.Plug do
@moduledoc """
Plugs for the recovery code strategy.
Handles verify and generate requests for recovery code authentication.
"""
alias AshAuthentication.{Errors, Info, Strategy, Strategy.RecoveryCode}
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]
@spec verify(Conn.t(), RecoveryCode.t()) :: Conn.t()
def verify(conn, strategy) do
case get_actor(conn) do
nil ->
store_authentication_result(conn, {:error, not_authenticated_error(strategy, :verify)})
user ->
params = subject_params(conn, strategy) |> Map.take(["code"]) |> Map.put("user", user)
opts = opts(conn)
case Strategy.action(strategy, :verify, params, opts) do
{:ok, user} ->
existing_strategies =
Ash.Resource.get_metadata(user, :authentication_strategies) || []
user_with_metadata =
user
|> Ash.Resource.put_metadata(
:authentication_strategies,
Enum.uniq(existing_strategies ++ [:recovery_code])
)
|> Ash.Resource.put_metadata(:recovery_code_used_at, DateTime.utc_now())
store_authentication_result(conn, {:ok, user_with_metadata})
error ->
store_authentication_result(conn, error)
end
end
end
@spec generate(Conn.t(), RecoveryCode.t()) :: Conn.t()
def generate(conn, strategy) do
case get_actor(conn) do
nil ->
store_authentication_result(conn, {:error, not_authenticated_error(strategy, :generate)})
user ->
params = %{"user" => user}
opts = opts(conn)
result = Strategy.action(strategy, :generate, params, opts)
store_authentication_result(conn, result)
end
end
defp not_authenticated_error(strategy, action) do
Errors.AuthenticationFailed.exception(
strategy: strategy,
caused_by: %{
module: __MODULE__,
strategy: strategy,
action: action,
message: "No authenticated user"
}
)
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