Packages
ash_authentication
5.0.0-rc.12
5.0.0-rc.12
5.0.0-rc.11
5.0.0-rc.10
5.0.0-rc.9
5.0.0-rc.8
5.0.0-rc.7
5.0.0-rc.6
5.0.0-rc.5
5.0.0-rc.4
5.0.0-rc.3
5.0.0-rc.2
5.0.0-rc.1
5.0.0-rc.0
4.14.1
4.14.0
4.13.7
4.13.6
4.13.5
4.13.4
4.13.3
4.13.2
retired
4.13.1
retired
4.13.0
4.12.0
4.11.0
4.10.0
4.9.9
4.9.8
4.9.7
4.9.6
4.9.5
4.9.4
4.9.3
4.9.2
4.9.1
4.9.0
4.8.7
4.8.6
4.8.5
4.8.3
4.8.2
4.8.1
4.8.0
4.7.6
4.7.5
4.7.4
4.7.3
4.7.2
4.7.1
4.7.0
4.6.4
4.6.3
4.6.2
4.6.1
4.6.0
4.5.6
4.5.5
4.5.4
4.5.3
4.5.2
4.5.1
4.5.0
4.4.9
4.4.8
4.4.7
4.4.6
4.4.5
4.4.4
4.4.3
4.4.2
4.4.1
4.4.0
4.3.12
4.3.11
4.3.10
4.3.9
4.3.8
4.3.7
4.3.6
4.3.5
4.3.4
4.3.3
4.3.2
4.3.1
4.3.0
4.2.7
4.2.6
4.2.5
4.2.4
4.2.3
4.2.2
4.2.1
4.2.0
4.1.0
4.0.4
4.0.3
4.0.2
4.0.1
4.0.0
4.0.0-rc.6
4.0.0-rc.5
4.0.0-rc.3
4.0.0-rc.2
4.0.0-rc.1
4.0.0-rc.0
3.12.4
3.12.3
3.12.2
3.12.1
3.12.0
3.11.16
3.11.15
3.11.14
3.11.13
3.11.12
3.11.11
3.11.10
3.11.9
3.11.8
3.11.7
3.11.6
3.11.5
3.11.4
3.11.3
3.11.2
3.11.1
3.11.0
3.10.8
3.10.7
3.10.6
3.10.5
3.10.4
3.10.3
3.10.2
3.10.1
3.10.0
3.9.6
3.9.5
3.9.4
3.9.3
3.9.2
3.9.1
3.9.0
3.8.0
3.7.9
3.7.8
3.7.6
3.7.5
3.7.4
3.7.3
3.7.2
3.7.1
3.7.0
3.6.1
3.6.0
3.5.3
3.5.2
3.5.1
3.5.0
3.3.1
3.3.0
3.2.2
3.2.1
3.2.0
3.1.0
3.0.3
Authentication extension for the Ash Framework.
Current section
Files
Jump to
Current section
Files
lib/ash_authentication/user_identity/upsert_identity_change.ex
# SPDX-FileCopyrightText: 2022 Alembic Pty Ltd
#
# SPDX-License-Identifier: MIT
defmodule AshAuthentication.UserIdentity.UpsertIdentityChange do
@moduledoc """
A change which upserts a user's identity into the user identity resource.
Expects the following arguments:
- `user_info` a map with string keys as returned from the OAuth2/OpenID
upstream provider.
- `oauth_tokens` a map with string keys containing the OAuth2 token
response.
- `user_id` the ID of the user this identity relates to.
- `strategy` the name of the strategy.
This is usually dynamically inserted into a generated action, however you can
add it to your own action if needed.
"""
use Ash.Resource.Change
alias Ash.{Changeset, Resource.Change}
alias AshAuthentication.Strategy.OAuth2
alias AshAuthentication.UserIdentity.Info
@doc false
@impl true
@spec change(Changeset.t(), keyword, Change.context()) :: Changeset.t()
def change(changeset, _opts, _context) do
cfg = Info.user_identity_options(changeset.resource)
user_info = Changeset.get_argument(changeset, :user_info)
oauth_tokens = Changeset.get_argument(changeset, :oauth_tokens)
user_id = Changeset.get_argument(changeset, cfg.user_id_attribute_name)
uid = OAuth2.uid_from_user_info(user_info)
changeset
|> Changeset.change_attribute(cfg.user_id_attribute_name, user_id)
|> Changeset.change_attribute(cfg.uid_attribute_name, uid)
|> Changeset.change_attribute(
cfg.access_token_attribute_name,
Map.get(oauth_tokens, "access_token")
)
|> Changeset.change_attribute(
cfg.access_token_expires_at_attribute_name,
expires_at(oauth_tokens, "expires_in")
)
|> then(fn changeset ->
if Map.get(oauth_tokens, "refresh_token") do
# A new non-nil refresh_token is always nice
Changeset.change_attribute(
changeset,
cfg.refresh_token_attribute_name,
oauth_tokens["refresh_token"] ||
Map.get(oauth_tokens, "refresh_token")
)
else
# Do not overwrite refresh_tokens with a new nil
changeset
end
end)
end
defp expires_at(oauth_tokens, field) do
oauth_tokens
|> Map.get(field)
|> case do
nil ->
nil
expires_in when is_binary(expires_in) ->
expires_in
|> String.to_integer()
|> from_now()
expires_in when is_number(expires_in) ->
expires_in
|> from_now()
end
end
defp from_now(seconds) do
DateTime.utc_now()
|> DateTime.add(seconds, :second)
end
end