Packages
ash_authentication
5.0.0-rc.12
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.
Current section
Files
Jump to
Current section
Files
lib/ash_authentication/strategies/otp/dsl.ex
# SPDX-FileCopyrightText: 2022 Alembic Pty Ltd
#
# SPDX-License-Identifier: MIT
defmodule AshAuthentication.Strategy.Otp.Dsl do
@moduledoc false
alias AshAuthentication.Strategy.{Custom, Otp}
alias Spark.Dsl.Entity
@doc false
@spec dsl :: Custom.entity()
def dsl do
%Entity{
name: :otp,
describe: "Strategy for authenticating using a one-time password sent to the user",
args: [{:optional, :name, :otp}],
hide: [:name],
target: Otp,
no_depend_modules: [:sender, :otp_generator],
schema: [
name: [
type: :atom,
doc: "Uniquely identifies the strategy.",
required: true
],
brute_force_strategy: [
type:
{:or,
[
{:literal, :rate_limit},
{:tuple, [{:literal, :audit_log}, :atom]},
{:tuple, [{:literal, :preparation}, {:behaviour, Ash.Resource.Preparation}]}
]},
doc: "How you are mitigating brute-force OTP checks.",
required: true
],
identity_field: [
type: :atom,
doc:
"The name of the attribute which uniquely identifies the user, usually something like `username` or `email_address`.",
default: :email
],
otp_lifetime: [
type:
{:or,
[
:pos_integer,
{:tuple, [:pos_integer, {:in, [:days, :hours, :minutes, :seconds]}]}
]},
doc:
"How long the OTP code is valid. If no unit is provided, then `minutes` is assumed.",
default: {10, :minutes}
],
otp_length: [
type: :pos_integer,
doc: "The length of the generated OTP code.",
default: 6
],
otp_characters: [
type:
{:in,
[
:unambiguous_uppercase,
:unambiguous_alphanumeric,
:digits_only,
:uppercase_letters_only
]},
doc: """
The character set used to generate OTP codes:
- `:unambiguous_uppercase` (default) — A–Z minus easily misread characters (I, L, O, S, Z)
- `:unambiguous_alphanumeric` — unambiguous letters and digits combined
- `:digits_only` — full 0–9
- `:uppercase_letters_only` — full A–Z
""",
default: :unambiguous_uppercase
],
otp_generator: [
type: :atom,
doc:
"A module that implements `generate/1` and `normalize/1`. Defaults to `AshAuthentication.Strategy.Otp.DefaultGenerator`.",
required: false
],
registration_enabled?: [
type: :boolean,
doc:
"Allows registering via OTP. Sign-in becomes an upsert action instead of a read action, so users who don't exist are created on first sign-in.",
default: false
],
case_sensitive?: [
type: :boolean,
doc:
"Whether OTP codes are matched case-sensitively. When `false` (the default), codes are uppercased before comparison so `\"xkptmh\"` matches `\"XKPTMH\"`.",
default: false
],
single_use_token?: [
type: :boolean,
doc: "Automatically revoke the OTP token once it's been used for sign in.",
default: true
],
request_action_name: [
type: :atom,
doc: "The name to use for the request action. Defaults to `request_<strategy_name>`.",
required: false
],
sign_in_action_name: [
type: :atom,
doc:
"The name to use for the sign in action. Defaults to `sign_in_with_<strategy_name>`.",
required: false
],
lookup_action_name: [
type: :atom,
doc:
"The action to use when looking up a user by their identity. Defaults to `get_by_<identity_field>`."
],
otp_param_name: [
type: :atom,
doc: "The name of the OTP parameter in the incoming sign-in request.",
default: :otp,
required: false
],
sender: [
type:
{:spark_function_behaviour, AshAuthentication.Sender,
{AshAuthentication.SenderFunction, 3}},
doc: "How to send the OTP code to the user.",
required: true
],
audit_log_window: [
type:
{:or,
[
:pos_integer,
{:tuple, [:pos_integer, {:in, [:days, :hours, :minutes, :seconds]}]}
]},
doc:
"Time window for counting failed attempts when using the `{:audit_log, ...}` brute force strategy. If no unit is provided, then `minutes` is assumed. Defaults to 5 minutes.",
required: false,
default: {5, :minutes}
],
audit_log_max_failures: [
type: :pos_integer,
doc:
"Maximum allowed failures within the window before blocking when using the `{:audit_log, ...}` brute force strategy. Defaults to 5.",
required: false,
default: 5
]
]
}
end
end