Social Login and Account Linking
Social login is an OIDC client integration (Chapter 9 from the other side), and that part is easy. The hard part is linking: deciding when a Google or Apple sign-in belongs to an existing account. Get linking wrong and you build an account-takeover feature.
Integration rules
- Use authorization code with PKCE, plus
stateandnonce, for every provider. - Validate the ID token: signature against the provider's JWKS,
iss,audequal to your client ID,exp, andnonce. - Key the federated identity on (issuer,
sub). Emails change and can be reassigned;subdoes not. - Store only what you need from the provider's profile, and record which provider supplied it.
Provider quirks to plan for
| Provider | Plan for |
|---|---|
| Sign in with Apple | Users can hide their email behind a private relay address; name is sent only on first authorization, so save it then |
Check email_verified; Workspace accounts carry an hd (hosted domain) claim you can use for B2B routing |
|
| Microsoft | Personal and work accounts share endpoints; use the tenant and iss to tell them apart, and validate the issuer per tenant |
| Others | Some providers do not verify email at all; treat their email as unverified |
Linking decision table
When a social sign-in arrives with an email that matches an existing account:
| Situation | Safe action |
|---|---|
| (issuer, sub) already linked | Sign in |
| Email matches, provider says verified, and your account's email is verified | Ask the user to sign in to the existing account first (password, passkey, or email code), then link |
| Email matches, but either side is unverified | Do not link; do not reveal the existing account in the UI; continue as if new and require email verification before any merge |
| No match | Create a new user, mark the email verified only if the provider verified it |
Automatic linking on email match alone is the classic pre-account-takeover pattern: an attacker registers your email at a provider that does not verify it, signs in, and inherits your account. Requiring proof of the existing account before linking closes it.
Unlinking
Let users unlink a provider only if they will still have another way to sign in. Require step-up, and notify them.
Common mistakes
- Linking on email without proof of the existing account.
- Trusting
emailfrom providers that do not setemail_verified. - Losing Apple's name on first sign-in and never getting it again.
Key takeaways
- Social login is an OIDC client integration; linking is the hard part.
- Key federated identities on (issuer, sub), never on email.
- Require proof of the existing account before linking a matching email.
- Save Sign in with Apple names on first authorization; you will not get them again.