fix(Confirmation): correctly generate confirmation token subjects. (#124)

This commit is contained in:
James Harton 2023-01-12 13:49:48 +13:00 committed by GitHub
parent 947a4c7283
commit 500ea353a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 17 additions and 16 deletions

View file

@ -97,7 +97,7 @@ defmodule AshAuthentication.AddOn.Confirmation do
provider: :confirmation, provider: :confirmation,
name: :confirm name: :confirm
alias Ash.Changeset alias Ash.{Changeset, Resource}
alias AshAuthentication.{AddOn.Confirmation, Jwt} alias AshAuthentication.{AddOn.Confirmation, Jwt}
@type t :: %Confirmation{ @type t :: %Confirmation{
@ -120,14 +120,14 @@ defmodule AshAuthentication.AddOn.Confirmation do
This will generate a token with the `"act"` claim set to the confirmation This will generate a token with the `"act"` claim set to the confirmation
action for the strategy, and the `"chg"` claim will contain any changes. action for the strategy, and the `"chg"` claim will contain any changes.
""" """
@spec confirmation_token(Confirmation.t(), Changeset.t()) :: @spec confirmation_token(Confirmation.t(), Changeset.t(), Resource.record()) ::
{:ok, String.t()} | :error | {:error, any} {:ok, String.t()} | :error | {:error, any}
def confirmation_token(strategy, changeset) do def confirmation_token(strategy, changeset, user) do
claims = %{"act" => strategy.confirm_action_name} claims = %{"act" => strategy.confirm_action_name}
token_lifetime = strategy.token_lifetime * 3600 token_lifetime = strategy.token_lifetime * 3600
with {:ok, token, _claims} <- with {:ok, token, _claims} <-
Jwt.token_for_user(changeset.data, claims, token_lifetime: token_lifetime), Jwt.token_for_user(user, claims, token_lifetime: token_lifetime),
:ok <- Confirmation.Actions.store_changes(strategy, token, changeset) do :ok <- Confirmation.Actions.store_changes(strategy, token, changeset) do
{:ok, token} {:ok, token}
end end

View file

@ -74,7 +74,7 @@ defmodule AshAuthentication.AddOn.Confirmation.ConfirmationHookChange do
changeset changeset
|> Changeset.after_action(fn _changeset, user -> |> Changeset.after_action(fn _changeset, user ->
strategy strategy
|> Confirmation.confirmation_token(original_changeset) |> Confirmation.confirmation_token(original_changeset, user)
|> case do |> case do
{:ok, token} -> {:ok, token} ->
{sender, send_opts} = strategy.sender {sender, send_opts} = strategy.sender

View file

@ -16,7 +16,7 @@ defmodule AshAuthentication.AddOn.Confirmation.ActionsTest do
user user
|> Changeset.for_update(:update, %{"username" => username()}) |> Changeset.for_update(:update, %{"username" => username()})
{:ok, token} = Confirmation.confirmation_token(strategy, changeset) {:ok, token} = Confirmation.confirmation_token(strategy, changeset, user)
Example.Repo.delete!(user) Example.Repo.delete!(user)
@ -40,7 +40,7 @@ defmodule AshAuthentication.AddOn.Confirmation.ActionsTest do
user user
|> Changeset.for_update(:update, %{"username" => new_username}) |> Changeset.for_update(:update, %{"username" => new_username})
{:ok, token} = Confirmation.confirmation_token(strategy, changeset) {:ok, token} = Confirmation.confirmation_token(strategy, changeset, user)
assert {:ok, confirmed_user} = Actions.confirm(strategy, %{"confirm" => token}, []) assert {:ok, confirmed_user} = Actions.confirm(strategy, %{"confirm" => token}, [])

View file

@ -7,7 +7,7 @@ defmodule AshAuthentication.AddOn.ConfirmationTest do
doctest Confirmation doctest Confirmation
describe "confirmation_token/2" do describe "confirmation_token/3" do
test "it generates a confirmation token" do test "it generates a confirmation token" do
{:ok, strategy} = Info.strategy(Example.User, :confirm) {:ok, strategy} = Info.strategy(Example.User, :confirm)
user = build_user() user = build_user()
@ -15,9 +15,10 @@ defmodule AshAuthentication.AddOn.ConfirmationTest do
new_username = username() new_username = username()
changeset = Changeset.for_update(user, :update, %{"username" => new_username}) changeset = Changeset.for_update(user, :update, %{"username" => new_username})
assert {:ok, token} = Confirmation.confirmation_token(strategy, changeset) assert {:ok, token} = Confirmation.confirmation_token(strategy, changeset, user)
assert {:ok, claims} = Jwt.peek(token) assert {:ok, claims} = Jwt.peek(token)
assert claims["act"] == to_string(strategy.confirm_action_name) assert claims["act"] == to_string(strategy.confirm_action_name)
assert claims["sub"] == to_string("user?id=#{user.id}")
end end
test "it stores changes in the token resource" do test "it stores changes in the token resource" do
@ -27,10 +28,9 @@ defmodule AshAuthentication.AddOn.ConfirmationTest do
new_username = username() new_username = username()
changeset = Changeset.for_update(user, :update, %{"username" => new_username}) changeset = Changeset.for_update(user, :update, %{"username" => new_username})
assert {:ok, token} = Confirmation.confirmation_token(strategy, changeset) assert {:ok, token} = Confirmation.confirmation_token(strategy, changeset, user)
assert {:ok, claims} = Jwt.peek(token) assert {:ok, claims} = Jwt.peek(token)
assert {:ok, changes} = Confirmation.Actions.get_changes(strategy, claims["jti"]) assert {:ok, changes} = Confirmation.Actions.get_changes(strategy, claims["jti"])
assert [{"username", new_username}] == Enum.to_list(changes) assert [{"username", new_username}] == Enum.to_list(changes)
end end
@ -41,9 +41,8 @@ defmodule AshAuthentication.AddOn.ConfirmationTest do
new_username = username() new_username = username()
changeset = Changeset.for_update(user, :update, %{"username" => new_username}) changeset = Changeset.for_update(user, :update, %{"username" => new_username})
assert {:ok, token} = Confirmation.confirmation_token(strategy, changeset) assert {:ok, token} = Confirmation.confirmation_token(strategy, changeset, user)
assert {:ok, claims} = Jwt.peek(token) assert {:ok, claims} = Jwt.peek(token)
refute Map.has_key?(claims, "chg") refute Map.has_key?(claims, "chg")
end end
end end
@ -55,7 +54,7 @@ defmodule AshAuthentication.AddOn.ConfirmationTest do
new_username = username() new_username = username()
changeset = Changeset.for_update(user, :update, %{"username" => new_username}) changeset = Changeset.for_update(user, :update, %{"username" => new_username})
assert {:ok, token} = Confirmation.confirmation_token(strategy, changeset) assert {:ok, token} = Confirmation.confirmation_token(strategy, changeset, user)
token token
end end

View file

@ -20,7 +20,8 @@ defmodule AshAuthentication.AddOn.Confirmation.PlugTest do
{:ok, token} = {:ok, token} =
Confirmation.confirmation_token( Confirmation.confirmation_token(
strategy, strategy,
Changeset.for_update(user, :update, %{"username" => username()}) Changeset.for_update(user, :update, %{"username" => username()}),
user
) )
Example.Repo.delete!(user) Example.Repo.delete!(user)
@ -63,7 +64,8 @@ defmodule AshAuthentication.AddOn.Confirmation.PlugTest do
{:ok, token} = {:ok, token} =
Confirmation.confirmation_token( Confirmation.confirmation_token(
strategy, strategy,
Changeset.for_update(user, :update, %{"username" => username()}) Changeset.for_update(user, :update, %{"username" => username()}),
user
) )
params = %{ params = %{