AshAuthentication. Strategy. OAuth2. UserResolver
(ash_authentication v5.0.0-rc.15)
Copy Markdown
View Source
Resolves which local user an OAuth2/OIDC sign-in belongs to.
Per OpenID Connect Core only the iss/sub claim combination uniquely and
stably identifies an end-user, so matching is driven by the user identity
resource - never by the email address.
Given the changeset for an OAuth2/OIDC register (upsert) action, the rules are:
If an identity already exists for this
(strategy, sub), the sign-in belongs to that user. The changeset's upsert keys are rewritten to that user's values so the upsert resolves to them (and the provider cannot change a user's email).Otherwise (a
subnot seen before):- If no local account matches the register action's
upsert_identity- proceed (a new account is created; if the email is not trusted and a confirmation add-on is present, that add-on gates it). - If the matched account already has an identity for this strategy
(a different
sub) - reject. A single account cannot have two identities for the same provider auto-linked. - If the strategy's
email_verifiedclaim can be trusted (trust_email_verified?and the claim is true) and the account was matched by that verified email - link the sign-in to that account. - Otherwise the email cannot be trusted to prove ownership of the matched
account. With
on_untrusted_email_match :reject(the default) the sign-in is rejected and the user must sign in with their existing method to link the provider. Withon_untrusted_email_match :confirmthe upsert is aborted with aConfirmationRequirederror so the caller can issue a confirmation to the existing account's email and link the provider only once the recipient proves ownership.
- If no local account matches the register action's
Why the link rule compares the email
An upsert_identity is not necessarily the email field - it can be a username
or any other claim the provider supplies, and the strategy has no setting that
names which attribute holds the email. A trusted email_verified claim
attests only that the person signing in owns some email, so on its own it
says nothing about an account matched on a username.
The link rule therefore requires the verified email to be the value that matched the account. The match is what carries the evidence: an account found by a value equal to the email the provider attested holds that email by construction of the query. The premise stops being an assumption and becomes a tested fact, with no need to know which attribute the email lives in.
Accounts matched on an email-shaped identifier
If the matched value is itself an email address - an account whose username
is an email, say - a sign-in that verifies that same address still links. The
person signing in has proven they own the identifier the account is keyed on,
so they can generally already take the account by password reset. Use an
email-keyed upsert_identity if you want the two to stay distinct.
A registration_enabled? false strategy has no upsert and no matched keys, so
it cannot test the premise this way. AshAuthentication.Strategy.OAuth2.SignInPreparation
applies the same rule against the strategy's email_field instead.
Rejections are surfaced as a generic AuthenticationFailed error to avoid
leaking which email addresses are registered.