mirror of
https://github.com/team-alembic/ash_authentication.git
synced 2024-09-19 12:52:55 +12:00
fix(Strategy.Password): Reset tokens are single use.
When a token is successfully used to reset a password then it is immediately revoked so that it cannot be used again. Closes #624.
This commit is contained in:
parent
2da79ce1d3
commit
ac24e83b2e
2 changed files with 24 additions and 1 deletions
|
@ -7,7 +7,7 @@ defmodule AshAuthentication.Strategy.Password.Actions do
|
|||
"""
|
||||
|
||||
alias Ash.{Changeset, Error.Invalid.NoSuchAction, Query, Resource}
|
||||
alias AshAuthentication.{Errors, Info, Jwt, Strategy.Password}
|
||||
alias AshAuthentication.{Errors, Info, Jwt, Strategy.Password, TokenResource}
|
||||
|
||||
@doc """
|
||||
Attempt to sign in a user.
|
||||
|
@ -236,6 +236,11 @@ defmodule AshAuthentication.Strategy.Password.Actions do
|
|||
}
|
||||
})
|
||||
|> Changeset.for_update(resettable.password_reset_action_name, params)
|
||||
|> Changeset.after_action(fn _changeset, record ->
|
||||
token_resource = Info.authentication_tokens_token_resource!(resource)
|
||||
:ok = TokenResource.revoke(token_resource, token)
|
||||
{:ok, record}
|
||||
end)
|
||||
|> Ash.update(options)
|
||||
else
|
||||
{:error, %Changeset{} = changeset} -> {:error, changeset}
|
||||
|
|
|
@ -5,6 +5,7 @@ defmodule AshAuthentication.Strategy.Password.ActionsTest do
|
|||
|
||||
alias AshAuthentication.{
|
||||
Errors.AuthenticationFailed,
|
||||
Errors.InvalidToken,
|
||||
Info,
|
||||
Jwt,
|
||||
Strategy.Password,
|
||||
|
@ -246,5 +247,22 @@ defmodule AshAuthentication.Strategy.Password.ActionsTest do
|
|||
assert user.hashed_password != updated_user.hashed_password
|
||||
assert strategy.hash_provider.valid?(new_password, updated_user.hashed_password)
|
||||
end
|
||||
|
||||
test "the token can only be used once" do
|
||||
user = build_user()
|
||||
{:ok, strategy} = Info.strategy(Example.User, :password)
|
||||
assert {:ok, token} = Password.reset_token_for(strategy, user)
|
||||
|
||||
new_password = password()
|
||||
|
||||
params = %{
|
||||
"reset_token" => token,
|
||||
"password" => new_password,
|
||||
"password_confirmation" => new_password
|
||||
}
|
||||
|
||||
assert {:ok, _} = Actions.reset(strategy, params, [])
|
||||
assert {:error, %InvalidToken{}} = Actions.reset(strategy, params, [])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue