Comeonin v5.1.1 Comeonin behaviour View Source
Defines a behaviour for higher-level password hashing functions.
Link to this section Summary
Callbacks
Hashes a password and returns the password hash in a map, with the password set to nil
Checks the password by comparing its hash with the password hash found in a user struct, or map
Runs the password hash function, but always returns false
Link to this section Types
opts()
View Source
opts() :: keyword()
opts() :: keyword()
password()
View Source
password() :: binary()
password() :: binary()
user_struct()
View Source
user_struct() :: map() | nil
user_struct() :: map() | nil
Link to this section Callbacks
add_hash(password, opts) View Source
Hashes a password and returns the password hash in a map, with the password set to nil.
In the default implementation, the key for the password hash is
:password_hash
. A different key can be used by using the hash_key
option.
Example with Ecto
The put_pass_hash
function below is an example of how you can use
add_hash
to add the password hash to the Ecto changeset.
defp put_pass_hash(%Ecto.Changeset{valid?: true, changes:
%{password: password}} = changeset) do
change(changeset, add_hash(password))
end
defp put_pass_hash(changeset), do: changeset
This function will return a changeset with %{password_hash: password_hash, password: nil}
added to the changes
map.
check_pass(user_struct, password, opts)
View Source
check_pass(user_struct(), password(), opts()) ::
{:ok, map()} | {:error, String.t()}
check_pass(user_struct(), password(), opts()) :: {:ok, map()} | {:error, String.t()}
Checks the password by comparing its hash with the password hash found in a user struct, or map.
The first argument to check_pass
should be a user struct, a regular
map, or nil.
In the default implementation, if the input to the first argument,
the user struct, is nil, then the no_user_verify
function is run,
so as to prevent user enumeration. This can be disabled by setting
the hide_user
option to false.
Example
The following is an example of calling this function with no options:
def verify_user(%{"password" => password} = params) do
params
|> Accounts.get_by()
|> check_pass(password)
end
The Accounts.get_by
function in this example takes the user parameters
(for example, email and password) as input and returns a user struct or nil.
no_user_verify(opts)
View Source
no_user_verify(opts()) :: false
no_user_verify(opts()) :: false
Runs the password hash function, but always returns false.
This function is intended to make it more difficult for any potential attacker to find valid usernames by using timing attacks. This function is only useful if it is used as part of a policy of hiding usernames.
Hiding usernames
In addition to keeping passwords secret, hiding the precise username can help make online attacks more difficult. An attacker would then have to guess a username / password combination, rather than just a password, to gain access.
This does not mean that the username should be kept completely secret. Adding a short numerical suffix to a user's name, for example, would be sufficient to increase the attacker's work considerably.
If you are implementing a policy of hiding usernames, it is important to make sure that the username is not revealed by any other part of your application.