Packages
ash_authentication
4.9.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/verifier.ex
defmodule AshAuthentication.Verifier do
@moduledoc """
The Authentication verifier.
Checks configuration constraints after compile.
"""
use Spark.Dsl.Verifier
alias AshAuthentication.{Info, Strategy, Strategy.Password}
alias Spark.{Dsl.Transformer, Error.DslError}
import AshAuthentication.Utils
@doc false
@impl true
@spec verify(map) ::
:ok
| {:error, term}
| {:warn, String.t() | list(String.t())}
def verify(dsl_state) do
with {:ok, _domain} <- validate_domain_presence(dsl_state),
:ok <- validate_tokens_may_be_required(dsl_state) do
if Info.authentication_session_identifier!(dsl_state) == :error and
not Info.authentication_tokens_require_token_presence_for_authentication?(dsl_state) do
{:error,
DslError.exception(
path: [:authentication, :session_identifier],
message: """
Must set `authentication.session_identifier` to either `:jti` or `:unsafe`,
unless `authentication.tokens.require_token_presence_for_authentication?` is set to `true`.
If you are seeing this error while upgrading ash_authentication, be aware that
updating this setting will log out all of your users.
When set to `:unsafe`, tokens are not revoked when the user logs out.
When set to `:jti`, we use this information to revoke tokens on logout.
We suggest setting `authentication.tokens.require_token_presence_for_authentication?` to `true`
to ensure that tokens are always present during authentication, which makes this option unnecessary.
Changing either of these settings will log out all of your users.
"""
)}
else
validate_token_resource(dsl_state)
end
end
end
defp validate_domain_presence(dsl_state) do
with domain when not is_nil(domain) <-
Transformer.get_option(dsl_state, [:authentication], :domain),
:ok <- assert_is_module(domain),
true <- function_exported?(domain, :spark_is, 0),
Ash.Domain <- domain.spark_is() do
{:ok, domain}
else
nil ->
{:error,
DslError.exception(
path: [:authentication, :domain],
message: "A domain module must be present"
)}
_ ->
{:error,
DslError.exception(
path: [:authentication, :domain],
message: "Module is not an `Ash.Domain`."
)}
end
end
defp validate_tokens_may_be_required(dsl_state) do
strategies_requiring_tokens =
dsl_state
|> Info.authentication_strategies()
|> Enum.filter(&Strategy.tokens_required?/1)
tokens_enabled? =
dsl_state
|> Info.authentication_tokens_enabled?()
case {strategies_requiring_tokens, tokens_enabled?} do
{[], _} ->
:ok
{_, true} ->
:ok
{[password | _], false}
when is_struct(password, Password) and is_map(password.resettable) ->
{:error,
DslError.exception(
path: [:authentication, :tokens, :enabled?],
message: """
The `#{password.name}` password authentication strategy requires tokens be enabled because reset tokens are in use.
To fix this error you can either:
1. disable password resets by removing the `resettable` configuration from your password strategy, or
"""
)}
{[password | _], false}
when is_struct(password, Password) and password.sign_in_tokens_enabled? ->
{:error,
DslError.exception(
path: [:authentication, :tokens, :enabled?],
message: """
The `#{password.name}` password authentication strategy requires tokens be enabled because sign-in tokens are in use.
To fix this error you can either:
1. disable sign in tokens by setting `sign_in_tokens_enabled? false` your password strategy, or
2. enable tokens.
"""
)}
{[strategy | _], false} ->
{:error,
DslError.exception(
path: [:authentication, :tokens, :enabled?],
message: """
The `#{inspect(strategy.name)}` authentication strategy requires tokens be enabled.
To fix this error you can either:
1. disable the `#{inspect(strategy.name)}` strategy, or
2. enable tokens.
"""
)}
end
end
@spec token_resource?(any()) :: {boolean(), any()}
defp token_resource?(module) do
{Spark.Dsl.is?(module, Ash.Resource), module}
end
defp validate_token_resource(dsl_state) do
if_tokens_enabled(dsl_state, fn dsl_state ->
with {:ok, resource} when is_truthy(resource) <-
Info.authentication_tokens_token_resource(dsl_state),
{true, _resource} <- token_resource?(resource) do
:ok
else
{:ok, falsy} when is_falsy(falsy) ->
:ok
{false, bad_token_resource} ->
{:error,
DslError.exception(
path: [:authentication, :tokens, :token_resource],
message: "`#{inspect(bad_token_resource)}` is not a valid token resource module name"
)}
end
end)
end
defp if_tokens_enabled(dsl_state, validator) when is_function(validator, 1) do
if Info.authentication_tokens_enabled?(dsl_state) do
validator.(dsl_state)
else
:ok
end
end
end