diff --git a/.tool-versions b/.tool-versions deleted file mode 100644 index 021359a..0000000 --- a/.tool-versions +++ /dev/null @@ -1,2 +0,0 @@ -elixir 1.15.6 -erlang 26.1 diff --git a/config/test.exs b/config/test.exs index b19f81d..5c49d2e 100644 --- a/config/test.exs +++ b/config/test.exs @@ -10,7 +10,7 @@ config :ash_authentication, Example.Repo, pool: Ecto.Adapters.SQL.Sandbox, pool_size: 10 -config :bcrypt_elixir, :log_rounds, 4 +# config :bcrypt_elixir, :log_rounds, 4 config :ash, :disable_async?, true diff --git a/documentation/dsls/DSL:-AshAuthentication.Strategy.Password.md b/documentation/dsls/DSL:-AshAuthentication.Strategy.Password.md index 5cfb2ca..0b8a93c 100644 --- a/documentation/dsls/DSL:-AshAuthentication.Strategy.Password.md +++ b/documentation/dsls/DSL:-AshAuthentication.Strategy.Password.md @@ -1,6 +1,7 @@ + # DSL: AshAuthentication.Strategy.Password Strategy for authenticating using local resources as the source of truth. @@ -47,7 +48,7 @@ end By default the password strategy will automatically generate the register, sign-in, reset-request and reset actions for you, however you're free to -define them yourself. If you do, then the action will be validated to ensure +define them yourself. If you do, then the action will be validated to ensure that all the needed configuration is present. If you wish to work with the actions directly from your code you can do so via @@ -94,87 +95,66 @@ Dispatching to plugs directly: See the [Testing guide](/documentation/topics/testing.md) for tips on testing resources using this strategy. - - ## authentication.strategies.password + ```elixir password name \\ :password ``` - Strategy for authenticating using local resources as the source of truth. ### Nested DSLs - * [resettable](#authentication-strategies-password-resettable) +- [resettable](#authentication-strategies-password-resettable) ### Examples + ``` password :password do identity_field :email hashed_password_field :hashed_password - hash_provider AshAuthentication.BcryptProvider confirmation_required? true end ``` - - - ### Options -| Name | Type | Default | Docs | -|------|------|---------|------| -| [`identity_field`](#authentication-strategies-password-identity_field){: #authentication-strategies-password-identity_field } | `atom` | `:username` | The name of the attribute which uniquely identifies the user, usually something like `username` or `email_address`. | -| [`hashed_password_field`](#authentication-strategies-password-hashed_password_field){: #authentication-strategies-password-hashed_password_field } | `atom` | `:hashed_password` | The name of the attribute within which to store the user's password once it has been hashed. | -| [`hash_provider`](#authentication-strategies-password-hash_provider){: #authentication-strategies-password-hash_provider } | `module` | `AshAuthentication.BcryptProvider` | A module which implements the `AshAuthentication.HashProvider` behaviour, to provide cryptographic hashing of passwords. | -| [`confirmation_required?`](#authentication-strategies-password-confirmation_required?){: #authentication-strategies-password-confirmation_required? } | `boolean` | `true` | Whether a password confirmation field is required when registering or changing passwords. | -| [`register_action_accept`](#authentication-strategies-password-register_action_accept){: #authentication-strategies-password-register_action_accept } | `list(atom)` | `[]` | A list of additional fields to be accepted in the register action. | -| [`password_field`](#authentication-strategies-password-password_field){: #authentication-strategies-password-password_field } | `atom` | `:password` | The name of the argument used to collect the user's password in plaintext when registering, checking or changing passwords. | -| [`password_confirmation_field`](#authentication-strategies-password-password_confirmation_field){: #authentication-strategies-password-password_confirmation_field } | `atom` | `:password_confirmation` | The name of the argument used to confirm the user's password in plaintext when registering or changing passwords. | -| [`register_action_name`](#authentication-strategies-password-register_action_name){: #authentication-strategies-password-register_action_name } | `atom` | | The name to use for the register action. Defaults to `register_with_` | -| [`registration_enabled?`](#authentication-strategies-password-registration_enabled?){: #authentication-strategies-password-registration_enabled? } | `boolean` | `true` | If you do not want new users to be able to register using this strategy, set this to false. | -| [`sign_in_action_name`](#authentication-strategies-password-sign_in_action_name){: #authentication-strategies-password-sign_in_action_name } | `atom` | | The name to use for the sign in action. Defaults to `sign_in_with_` | -| [`sign_in_enabled?`](#authentication-strategies-password-sign_in_enabled?){: #authentication-strategies-password-sign_in_enabled? } | `boolean` | `true` | If you do not want new users to be able to sign in using this strategy, set this to false. | -| [`sign_in_tokens_enabled?`](#authentication-strategies-password-sign_in_tokens_enabled?){: #authentication-strategies-password-sign_in_tokens_enabled? } | `boolean` | `true` | Whether or not to support generating short lived sign in tokens. Requires the resource to have tokens enabled. | -| [`sign_in_token_lifetime`](#authentication-strategies-password-sign_in_token_lifetime){: #authentication-strategies-password-sign_in_token_lifetime } | `pos_integer \| {pos_integer, :days \| :hours \| :minutes \| :seconds}` | `{60, :seconds}` | A lifetime for which a generated sign in token will be valid, if `sign_in_tokens_enabled?`. Unit defaults to `:seconds`. | - +| Name | Type | Default | Docs | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| [`identity_field`](#authentication-strategies-password-identity_field){: #authentication-strategies-password-identity_field } | `atom` | `:username` | The name of the attribute which uniquely identifies the user, usually something like `username` or `email_address`. | +| [`hashed_password_field`](#authentication-strategies-password-hashed_password_field){: #authentication-strategies-password-hashed_password_field } | `atom` | `:hashed_password` | The name of the attribute within which to store the user's password once it has been hashed. | +| [`hash_provider`](#authentication-strategies-password-hash_provider){: #authentication-strategies-password-hash_provider } | `module` | `AshAuthentication.BcryptProvider` | A module which implements the `AshAuthentication.HashProvider` behaviour, to provide cryptographic hashing of passwords. | +| [`confirmation_required?`](#authentication-strategies-password-confirmation_required?){: #authentication-strategies-password-confirmation_required? } | `boolean` | `true` | Whether a password confirmation field is required when registering or changing passwords. | +| [`register_action_accept`](#authentication-strategies-password-register_action_accept){: #authentication-strategies-password-register_action_accept } | `list(atom)` | `[]` | A list of additional fields to be accepted in the register action. | +| [`password_field`](#authentication-strategies-password-password_field){: #authentication-strategies-password-password_field } | `atom` | `:password` | The name of the argument used to collect the user's password in plaintext when registering, checking or changing passwords. | +| [`password_confirmation_field`](#authentication-strategies-password-password_confirmation_field){: #authentication-strategies-password-password_confirmation_field } | `atom` | `:password_confirmation` | The name of the argument used to confirm the user's password in plaintext when registering or changing passwords. | +| [`register_action_name`](#authentication-strategies-password-register_action_name){: #authentication-strategies-password-register_action_name } | `atom` | | The name to use for the register action. Defaults to `register_with_` | +| [`registration_enabled?`](#authentication-strategies-password-registration_enabled?){: #authentication-strategies-password-registration_enabled? } | `boolean` | `true` | If you do not want new users to be able to register using this strategy, set this to false. | +| [`sign_in_action_name`](#authentication-strategies-password-sign_in_action_name){: #authentication-strategies-password-sign_in_action_name } | `atom` | | The name to use for the sign in action. Defaults to `sign_in_with_` | +| [`sign_in_enabled?`](#authentication-strategies-password-sign_in_enabled?){: #authentication-strategies-password-sign_in_enabled? } | `boolean` | `true` | If you do not want new users to be able to sign in using this strategy, set this to false. | +| [`sign_in_tokens_enabled?`](#authentication-strategies-password-sign_in_tokens_enabled?){: #authentication-strategies-password-sign_in_tokens_enabled? } | `boolean` | `true` | Whether or not to support generating short lived sign in tokens. Requires the resource to have tokens enabled. | +| [`sign_in_token_lifetime`](#authentication-strategies-password-sign_in_token_lifetime){: #authentication-strategies-password-sign_in_token_lifetime } | `pos_integer \| {pos_integer, :days \| :hours \| :minutes \| :seconds}` | `{60, :seconds}` | A lifetime for which a generated sign in token will be valid, if `sign_in_tokens_enabled?`. Unit defaults to `:seconds`. | ## authentication.strategies.password.resettable - Configure password reset options for the resource - - - - - ### Options -| Name | Type | Default | Docs | -|------|------|---------|------| -| [`sender`](#authentication-strategies-password-resettable-sender){: #authentication-strategies-password-resettable-sender .spark-required} | `(any, any, any -> any) \| module` | | The sender to use when sending password reset instructions. | -| [`token_lifetime`](#authentication-strategies-password-resettable-token_lifetime){: #authentication-strategies-password-resettable-token_lifetime } | `pos_integer \| {pos_integer, :days \| :hours \| :minutes \| :seconds}` | `{3, :days}` | How long should the reset token be valid. If no unit is provided `:hours` is assumed. | -| [`request_password_reset_action_name`](#authentication-strategies-password-resettable-request_password_reset_action_name){: #authentication-strategies-password-resettable-request_password_reset_action_name } | `atom` | | The name to use for the action which generates a password reset token. Defaults to `request_password_reset_with_`. | -| [`password_reset_action_name`](#authentication-strategies-password-resettable-password_reset_action_name){: #authentication-strategies-password-resettable-password_reset_action_name } | `atom` | | The name to use for the action which actually resets the user's password. Defaults to `password_reset_with_`. | - - - - +| Name | Type | Default | Docs | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------- | +| [`sender`](#authentication-strategies-password-resettable-sender){: #authentication-strategies-password-resettable-sender .spark-required} | `(any, any, any -> any) \| module` | | The sender to use when sending password reset instructions. | +| [`token_lifetime`](#authentication-strategies-password-resettable-token_lifetime){: #authentication-strategies-password-resettable-token_lifetime } | `pos_integer \| {pos_integer, :days \| :hours \| :minutes \| :seconds}` | `{3, :days}` | How long should the reset token be valid. If no unit is provided `:hours` is assumed. | +| [`request_password_reset_action_name`](#authentication-strategies-password-resettable-request_password_reset_action_name){: #authentication-strategies-password-resettable-request_password_reset_action_name } | `atom` | | The name to use for the action which generates a password reset token. Defaults to `request_password_reset_with_`. | +| [`password_reset_action_name`](#authentication-strategies-password-resettable-password_reset_action_name){: #authentication-strategies-password-resettable-password_reset_action_name } | `atom` | | The name to use for the action which actually resets the user's password. Defaults to `password_reset_with_`. | ### Introspection Target: `AshAuthentication.Strategy.Password.Resettable` - - - ### Introspection Target: `AshAuthentication.Strategy.Password` - - diff --git a/documentation/topics/testing.md b/documentation/topics/testing.md index bb226ba..499743b 100644 --- a/documentation/topics/testing.md +++ b/documentation/topics/testing.md @@ -10,5 +10,5 @@ AshAuthentication uses `bcrypt_elixir` for hashing passwords for secure storage, # in config/test.exs # Do NOT set this value for production -config :bcrypt_elixir, log_rounds: 1 +# config :bcrypt_elixir, log_rounds: 1 ``` diff --git a/lib/ash_authentication/bcrypt_provider.ex b/lib/ash_authentication/fake_provider.ex similarity index 82% rename from lib/ash_authentication/bcrypt_provider.ex rename to lib/ash_authentication/fake_provider.ex index beec39a..3b06299 100644 --- a/lib/ash_authentication/bcrypt_provider.ex +++ b/lib/ash_authentication/fake_provider.ex @@ -1,4 +1,4 @@ -defmodule AshAuthentication.BcryptProvider do +defmodule AshAuthentication.FakeProvider do @moduledoc """ Provides the default implementation of `AshAuthentication.HashProvider` using `Bcrypt`. """ @@ -15,7 +15,7 @@ defmodule AshAuthentication.BcryptProvider do """ @impl true @spec hash(String.t()) :: {:ok, String.t()} | :error - def hash(input) when is_binary(input), do: {:ok, Bcrypt.hash_pwd_salt(input)} + def hash(input) when is_binary(input), do: {:ok, input} def hash(_), do: :error @doc """ @@ -30,7 +30,7 @@ defmodule AshAuthentication.BcryptProvider do @impl true @spec valid?(input :: String.t(), hash :: String.t()) :: boolean def valid?(input, hash) when is_binary(input) and is_binary(hash), - do: Bcrypt.verify_pass(input, hash) + do: input == hash @doc """ Simulate a password check to help avoid timing attacks. @@ -42,5 +42,5 @@ defmodule AshAuthentication.BcryptProvider do """ @impl true @spec simulate :: false - def simulate, do: Bcrypt.no_user_verify() + def simulate, do: :ok end diff --git a/lib/ash_authentication/strategies/password.ex b/lib/ash_authentication/strategies/password.ex index ea9cb1e..12ec960 100644 --- a/lib/ash_authentication/strategies/password.ex +++ b/lib/ash_authentication/strategies/password.ex @@ -95,7 +95,7 @@ defmodule AshAuthentication.Strategy.Password do """ defstruct confirmation_required?: false, - hash_provider: AshAuthentication.BcryptProvider, + hash_provider: AshAuthentication.FakeProvider, hashed_password_field: :hashed_password_field, identity_field: :username, name: nil, diff --git a/lib/ash_authentication/strategies/password/dsl.ex b/lib/ash_authentication/strategies/password/dsl.ex index 1f99f18..d211981 100644 --- a/lib/ash_authentication/strategies/password/dsl.ex +++ b/lib/ash_authentication/strategies/password/dsl.ex @@ -53,7 +53,7 @@ defmodule AshAuthentication.Strategy.Password.Dsl do type: {:behaviour, AshAuthentication.HashProvider}, doc: "A module which implements the `AshAuthentication.HashProvider` behaviour, to provide cryptographic hashing of passwords.", - default: AshAuthentication.BcryptProvider + default: AshAuthentication.FakeProvider ], confirmation_required?: [ type: :boolean, diff --git a/mix.exs b/mix.exs index 97b2ad2..0195a8e 100644 --- a/mix.exs +++ b/mix.exs @@ -175,7 +175,7 @@ defmodule AshAuthentication.MixProject do [ {:ash, ash_version("~> 3.0.0-rc.6")}, {:assent, "~> 0.2 and >= 0.2.8"}, - {:bcrypt_elixir, "~> 3.0"}, + # {:bcrypt_elixir, "~> 3.0"}, {:castore, "~> 1.0"}, {:finch, "~> 0.18.0"}, {:jason, "~> 1.4"},