AshAuthentication.Strategy.Totp (ash_authentication v5.0.0-rc.6)

Copy Markdown View Source

Strategy for Time-based One-Time Password (TOTP) authentication.

Provides TOTP support via nimble_totp, allowing users to authenticate using time-based codes from authenticator apps like Google Authenticator, Authy, or 1Password.

Requirements

Your resource needs to meet the following minimum requirements:

  1. Have a primary key.
  2. An identity field (e.g., email or username) for identifying users.
  3. A sensitive binary field for storing the TOTP secret.
  4. A sensitive datetime field for tracking the last successful TOTP authentication.
  5. A brute force protection strategy (rate limiting, audit log, or custom preparation).

Example

defmodule MyApp.Accounts.User do
  use Ash.Resource,
    extensions: [AshAuthentication],
    domain: MyApp.Accounts

  attributes do
    uuid_primary_key :id
    attribute :email, :ci_string, allow_nil?: false, public?: true
    attribute :totp_secret, :binary, sensitive?: true
    attribute :last_totp_at, :utc_datetime, sensitive?: true
  end

  authentication do
    tokens do
      enabled? true
      token_resource MyApp.Accounts.Token
    end

    strategies do
      totp do
        identity_field :email
        issuer "MyApp"
        brute_force_strategy {:audit_log, :my_audit_log}
      end
    end

    add_ons do
      audit_log :my_audit_log do
        audit_log_resource MyApp.Accounts.AuditLog
        log_actions [:sign_in_with_totp, :verify_with_totp, :confirm_setup_with_totp]
      end
    end
  end

  identities do
    identity :unique_email, [:email]
  end
end

Actions

The TOTP strategy can generate up to four actions:

  • setup - Generates a new TOTP secret for the user. Returns the user with a totp_url calculation that can be rendered as a QR code.
  • confirm_setup - When confirm_setup_enabled? is true, this action verifies a TOTP code before activating the secret. Requires tokens to be enabled.
  • sign_in - Authenticates a user using their identity and a TOTP code.
  • verify - Checks if a TOTP code is valid for a given user (without signing in).

Brute Force Protection

TOTP codes have a small keyspace (typically 6 digits), making them vulnerable to brute force attacks. You must configure a brute_force_strategy:

  • :rate_limit - Uses AshRateLimiter to limit attempts.
  • {:audit_log, :audit_log_name} - Uses an audit log to track failed attempts.
  • {:preparation, ModuleName} - Custom preparation for rate limiting.

Working with Actions

You can interact with TOTP actions via the AshAuthentication.Strategy protocol:

iex> strategy = AshAuthentication.Info.strategy!(MyApp.Accounts.User, :totp)
...> {:ok, user} = AshAuthentication.Strategy.action(strategy, :setup, %{user: existing_user})
...> user.totp_url_for_totp  # QR code URL

iex> {:ok, true} = AshAuthentication.Strategy.action(strategy, :verify, %{user: user, code: "123456"})

Summary

Types

t()

@type t() :: %AshAuthentication.Strategy.Totp{
  __identifier__: any(),
  __spark_metadata__: any(),
  audit_log_max_failures: pos_integer(),
  audit_log_window:
    pos_integer() | {pos_integer(), :days | :hours | :minutes | :seconds},
  brute_force_strategy:
    :rate_limit | {:audit_log, atom()} | {:preparation, module()},
  confirm_setup_action_name: atom(),
  confirm_setup_enabled?: boolean(),
  grace_period: non_neg_integer() | nil,
  identity_field: atom(),
  issuer: String.t(),
  last_totp_at_field: atom(),
  name: atom(),
  period: pos_integer(),
  read_secret_from: atom() | nil,
  resource: Ash.Resource.t(),
  secret_field: atom(),
  secret_length: pos_integer(),
  setup_action_name: atom(),
  setup_enabled?: boolean(),
  setup_token_lifetime:
    pos_integer() | {pos_integer(), :days | :hours | :minutes | :seconds},
  sign_in_action_name: atom(),
  sign_in_enabled?: boolean(),
  totp_url_field: atom(),
  verify_action_name: atom(),
  verify_enabled?: boolean()
}

Functions

transform(entity, dsl)

Callback implementation for AshAuthentication.Strategy.Custom.transform/2.

verify(strategy, dsl)

Callback implementation for AshAuthentication.Strategy.Custom.verify/2.