Packages
ash_authentication
5.0.0-rc.4
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/hash_provider.ex
# SPDX-FileCopyrightText: 2022 Alembic Pty Ltd
#
# SPDX-License-Identifier: MIT
defmodule AshAuthentication.HashProvider do
@moduledoc """
A behaviour providing password hashing.
"""
@doc """
Given some user input as a string, convert it into it's hashed form.
"""
@callback hash(input :: String.t()) :: {:ok, hash :: String.t()} | :error
@doc """
Hash with action context.
An optional variant of `hash/1` that receives the Ash context from the
current action (changeset or action input). This enables hash providers
that need external state — for example, a shared-salt provider can read
a pre-generated salt from the context.
When implemented, this callback is preferred over `hash/1` by the
recovery code strategy's hashing change and verify action.
"""
@callback hash(input :: String.t(), context :: map()) ::
{:ok, hash :: String.t()} | :error
@doc """
Check if the user input matches the hash.
"""
@callback valid?(input :: String.t(), hash :: String.t()) :: boolean()
@doc """
Attempt to defeat timing attacks by simulating a password hash check.
See [Bcrypt.no_user_verify/1](https://hexdocs.pm/bcrypt_elixir/Bcrypt.html#no_user_verify/1) for more information.
"""
@callback simulate :: false
@doc """
The minimum bits of input entropy required for this hash provider to be safe.
Slow hash providers like bcrypt and argon2 return `0` because their
computational cost makes brute-force attacks impractical regardless of input
entropy. Fast deterministic hash providers like SHA-256 require high-entropy
inputs (e.g. 60+ bits) because their speed makes low-entropy inputs
vulnerable to offline brute-force attacks.
"""
@callback minimum_entropy() :: non_neg_integer()
@doc """
Whether the same input always produces the same hash output.
Deterministic providers (e.g. SHA-256) allow atomic database-level
verification by hashing the input and matching directly against stored
values. Non-deterministic providers (e.g. bcrypt, argon2) use random salts,
so verification requires loading stored hashes and comparing individually.
"""
@callback deterministic?() :: boolean()
@optional_callbacks hash: 2
@doc """
Calls `hash/2` if the provider implements it, otherwise falls back to `hash/1`.
"""
@spec call_hash(module(), String.t(), map()) :: {:ok, String.t()} | :error
def call_hash(provider, input, context) do
if function_exported?(provider, :hash, 2) do
provider.hash(input, context)
else
provider.hash(input)
end
end
end