Prompt
How do I handle account linking when users log in with different providers?
Latest observation
To handle account linking across multiple login providers cleanly, the key is to separate identity from account.
Core principle
Treat each provider login as an external identity that can map to one internal user account.
- Internal account = your app’s user record
- External identity = Google/Facebook/Apple/GitHub/etc. user ID from that provider
A single user account can have multiple external identities linked to it.
Recommended model
1) Store users separately from provider identities
Typical tables/collections:
users
- id
- name
- created_at
- other profile fields
user_identities
- id
- user_id
- provider
- provider_user_id
- email_at_provider_login
- access_token/refresh_token if needed
- created_at
Enforce a unique constraint on:
(provider, provider_user_id)
This prevents the same provider identity from linking to multiple accounts.
2) Decide your linking strategy
There are 3 common approaches:
A. Automatic linking by verified email
If a user logs in with Google and later logs in with Apple using the same verified email, link them automatically.
Pros
- Smooth user experience
- Fewer duplicate accounts
Cons
- Risky if email verification is weak or inconsistent across providers
- Some providers may hide email or allow unverified email
Only auto-link if:
- the email is verified by the provider
- and you trust that provider’s verification
- and your app policy allows it
B. Explicit user-initiated linking
If the user is already signed in, let them click:
- “Link Google”
- “Link GitHub”
- “Link Apple”
Then complete OAuth and attach the provider identity to the currently authenticated account.
Pros
- Safest
- Clear user intent
Cons
- Slightly more work for the user
This is usually the best default.
C. Merge-on-login with confirmation
If a login comes in with an email that matches an existing account, show:
- “An account already exists with this email. Do you want to link these accounts?”
Then require re-authentication or email confirmation before merging.
Pros
- Good balance of UX and safety
Cons
- More flow complexity
3) Handle sign-in flow carefully
When a user logs in with a provider:
- Find the external identity by
(provider, provider_user_id) - If found:
- sign them into the linked internal user
- If not found:
- check whether the provider returns a verified email
- if email matches an existing user, decide whether to:
- auto-link, or
- prompt for linking
- otherwise create a new internal user and link this identity
4) Avoid unsafe automatic merges
Do not merge accounts based only on:
- unverified email
- display name
- provider profile name
- similar-looking data
These are not strong enough to prove ownership.
Be especially careful with:
- email aliases
- disposable emails
- providers that don’t always return email
- privacy-focused providers that hide email by default
5) Best practices for security
Require proof of ownership when linking
If a user wants to link a new provider to an existing account, make sure they are:
- already authenticated in your app, or
- re-authenticated with their password / MFA / existing provider
Prevent account takeover
If someone logs in with a provider using an email that matches an existing account, don’t immediately give access unless the email is verified and your policy supports that.
Support unlinking carefully
Allow users to unlink providers, but prevent them from removing the last sign-in method unless they have another way to access the account.
Example rule:
- user must always have at least one recovery/login method
6) Suggested user experience
In account settings:
- Connected accounts:
- Google — Linked
- GitHub — Linked
- Apple — Not linked
Buttons:
- Link provider
- Unlink provider
On login:
- “Continue with Google”
- If existing account found: “This account is already linked. Signing you in.”
- If conflict: “An account with this email exists. Please sign in to link this provider.”
7) Common edge cases
Same person, different emails
A user may use different emails on different providers. In that case, you’ll need explicit linking instead of email-based matching.
Same email, different people
This can happen with shared inboxes or misconfigured provider data. Don’t rely on email alone unless verified and trusted.
Provider returns no email
Some providers don’t share email. Then you must use explicit linking or create a new account.
Provider account changed
If the user changes their email at the provider, your app should still identify them by provider subject/user ID, not email.
8) Practical recommendation
If you want a safe default:
- Use external identity IDs as the primary login key
- Allow user-initiated linking from account settings
- Optionally support verified-email auto-linking only for trusted providers
- Never merge accounts without a strong proof of ownership
If you want, I can also provide:
- a sample database schema,
- OAuth linking flow pseudocode, or
- a strategy for specific providers like Google + Apple + GitHub.