# `AshAuthentication.Strategy.RecoveryCode`
[🔗](https://github.com/team-alembic/ash_authentication/blob/main/lib/ash_authentication/strategies/recovery_code.ex#L5)

Strategy for recovery code authentication.

Allows users to authenticate using one-time recovery codes when they can't
access their primary authentication method (e.g., TOTP authenticator app).
Recovery codes are single-use and deleted after successful verification.

## Requirements

1. A separate Ash resource for storing recovery codes with:
   - A sensitive string attribute for the hashed code
   - A `belongs_to` relationship to the user resource
   - `create`, `read`, and `destroy` actions
2. A `has_many` relationship on the user resource pointing to recovery codes
3. A brute force protection strategy (rate limiting, audit log, or custom preparation)

## Example

```elixir
defmodule MyApp.Accounts.RecoveryCode do
  use Ash.Resource,
    data_layer: AshPostgres.DataLayer,
    domain: MyApp.Accounts

  attributes do
    uuid_primary_key :id
    attribute :code, :string, sensitive?: true, allow_nil?: false
  end

  relationships do
    belongs_to :user, MyApp.Accounts.User, allow_nil?: false
  end

  actions do
    defaults [:read, :destroy]
    create :create do
      accept [:code]
      argument :user_id, :uuid, allow_nil?: false
      change manage_relationship(:user_id, :user, type: :append)
    end
  end
end

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

  relationships do
    has_many :recovery_codes, MyApp.Accounts.RecoveryCode
  end

  authentication do
    strategies do
      recovery_code do
        recovery_code_resource MyApp.Accounts.RecoveryCode
        hash_provider AshAuthentication.BcryptProvider
        brute_force_strategy {:preparation, MyApp.NoopPreparation}
      end
    end
  end
end
```

## Actions

The recovery code strategy generates up to two actions:

- **verify** - Verifies a recovery code for a user. On success, deletes the
  used code and returns the user. On failure, returns nil.
- **generate** - When `generate_enabled?` is true, generates new recovery codes
  for a user. Deletes any existing codes and returns the plaintext codes.

# `t`

```elixir
@type t() :: %AshAuthentication.Strategy.RecoveryCode{
  __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()},
  code_alphabet: String.t(),
  code_field: atom(),
  code_length: pos_integer(),
  generate_action_name: atom() | nil,
  generate_enabled?: boolean(),
  hash_provider: module(),
  name: atom(),
  provider: :recovery_code,
  recovery_code_count: pos_integer(),
  recovery_code_resource: module() | nil,
  recovery_codes_relationship_name: atom(),
  resource: Ash.Resource.t() | nil,
  user_relationship_name: atom(),
  verify_action_name: atom() | nil
}
```

# `transform`

# `verify`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
