mirror of
https://github.com/team-alembic/ash_authentication.git
synced 2024-09-19 21:03:23 +12:00
fix: correctly generate sign-in tokens when requested.
This commit is contained in:
parent
d8588b9b89
commit
81236e1ed5
4 changed files with 64 additions and 28 deletions
|
@ -38,28 +38,23 @@ defmodule AshAuthentication.Strategy.Password.SignInPreparation do
|
||||||
if strategy.hash_provider.valid?(
|
if strategy.hash_provider.valid?(
|
||||||
password,
|
password,
|
||||||
Map.get(record, strategy.hashed_password_field)
|
Map.get(record, strategy.hashed_password_field)
|
||||||
),
|
) do
|
||||||
do:
|
token_type = query.context[:token_type] || :user
|
||||||
{:ok,
|
|
||||||
[
|
{:ok, [maybe_generate_token(token_type, record, strategy)]}
|
||||||
maybe_generate_token(
|
else
|
||||||
query.context[:token_type] || :user,
|
{:error,
|
||||||
record,
|
AuthenticationFailed.exception(
|
||||||
strategy
|
strategy: strategy,
|
||||||
)
|
query: query,
|
||||||
]},
|
caused_by: %{
|
||||||
else:
|
module: __MODULE__,
|
||||||
{:error,
|
action: query.action,
|
||||||
AuthenticationFailed.exception(
|
resource: query.resource,
|
||||||
strategy: strategy,
|
message: "Password is not valid"
|
||||||
query: query,
|
}
|
||||||
caused_by: %{
|
)}
|
||||||
module: __MODULE__,
|
end
|
||||||
action: query.action,
|
|
||||||
resource: query.resource,
|
|
||||||
message: "Password is not valid"
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
|
|
||||||
query, [] ->
|
query, [] ->
|
||||||
strategy.hash_provider.simulate()
|
strategy.hash_provider.simulate()
|
||||||
|
@ -118,11 +113,11 @@ defmodule AshAuthentication.Strategy.Password.SignInPreparation do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp generate_token(purpose, record, strategy)
|
defp generate_token(:sign_in, record, strategy) when strategy.sign_in_tokens_enabled? do
|
||||||
when is_integer(strategy.sign_in_token_lifetime) and purpose == :sign_in do
|
|
||||||
{:ok, token, _claims} =
|
{:ok, token, _claims} =
|
||||||
Jwt.token_for_user(record, %{"purpose" => to_string(purpose)},
|
Jwt.token_for_user(record, %{"purpose" => "sign_in"},
|
||||||
token_lifetime: strategy.sign_in_token_lifetime
|
token_lifetime: strategy.sign_in_token_lifetime,
|
||||||
|
purpose: :sign_in
|
||||||
)
|
)
|
||||||
|
|
||||||
Ash.Resource.put_metadata(record, :token, token)
|
Ash.Resource.put_metadata(record, :token, token)
|
||||||
|
|
|
@ -24,7 +24,7 @@ defmodule AshAuthentication.Strategy.Password.StrategyTest do
|
||||||
assert MapSet.equal?(phases, MapSet.new(~w[register sign_in reset_request reset]a))
|
assert MapSet.equal?(phases, MapSet.new(~w[register sign_in reset_request reset]a))
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns the correct phases when the strategy doesn't suport resetting" do
|
test "it returns the correct phases when the strategy doesn't support resetting" do
|
||||||
strategy = %Password{}
|
strategy = %Password{}
|
||||||
|
|
||||||
phases =
|
phases =
|
||||||
|
@ -48,7 +48,7 @@ defmodule AshAuthentication.Strategy.Password.StrategyTest do
|
||||||
assert MapSet.equal?(actions, MapSet.new(~w[register sign_in reset_request reset]a))
|
assert MapSet.equal?(actions, MapSet.new(~w[register sign_in reset_request reset]a))
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns the correct actions when the strategy doesn't suport resetting" do
|
test "it returns the correct actions when the strategy doesn't support resetting" do
|
||||||
strategy = %Password{}
|
strategy = %Password{}
|
||||||
|
|
||||||
actions =
|
actions =
|
||||||
|
|
|
@ -13,6 +13,8 @@ defmodule AshAuthentication.Strategy.PasswordTest do
|
||||||
Strategy.Password.Resettable
|
Strategy.Password.Resettable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alias Example.User
|
||||||
|
|
||||||
doctest Password
|
doctest Password
|
||||||
|
|
||||||
describe "reset_token_for/1" do
|
describe "reset_token_for/1" do
|
||||||
|
@ -26,4 +28,39 @@ defmodule AshAuthentication.Strategy.PasswordTest do
|
||||||
assert claims["act"] == to_string(resettable.password_reset_action_name)
|
assert claims["act"] == to_string(resettable.password_reset_action_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "regressions" do
|
||||||
|
test "only one user token is generated for a new user registration" do
|
||||||
|
user = build_user()
|
||||||
|
subject = AshAuthentication.user_to_subject(user)
|
||||||
|
|
||||||
|
tokens = Example.Token |> Ash.read!() |> Enum.group_by(& &1.purpose)
|
||||||
|
assert [%{subject: ^subject}] = tokens["user"]
|
||||||
|
|
||||||
|
token_types = tokens |> Map.keys() |> MapSet.new()
|
||||||
|
assert token_types == MapSet.new(["user", "confirm"])
|
||||||
|
end
|
||||||
|
|
||||||
|
test "only one token is generated for a user sign-in" do
|
||||||
|
user = build_user()
|
||||||
|
subject = AshAuthentication.user_to_subject(user)
|
||||||
|
|
||||||
|
Example.Token |> Ash.bulk_destroy!(:destroy, %{})
|
||||||
|
|
||||||
|
strategy = AshAuthentication.Info.strategy!(User, :password)
|
||||||
|
|
||||||
|
{:ok, _signed_in_user} =
|
||||||
|
Strategy.action(
|
||||||
|
strategy,
|
||||||
|
:sign_in,
|
||||||
|
%{
|
||||||
|
username: user.username,
|
||||||
|
password: user.__metadata__.password
|
||||||
|
},
|
||||||
|
context: [token_type: :sign_in]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert [%{subject: ^subject, purpose: "sign_in"}] = Example.Token |> Ash.read!()
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,4 +9,8 @@ defmodule Example.Token do
|
||||||
table("tokens")
|
table("tokens")
|
||||||
repo(Example.Repo)
|
repo(Example.Repo)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
actions do
|
||||||
|
defaults [:read, :destroy]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue