Packages
ash_authentication
4.0.2
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.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/ash_authentication/user_identity/upsert_identity_change.ex
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.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 =
user_info
# uid is a convention
# sub is supposedly from the spec
# id is from what has been seen from Google
|> Map.take(["uid", "sub", "id", :uid, :sub, :id])
|> Map.values()
|> Enum.reject(&is_nil/1)
|> List.first()
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