Prompt
My app keeps creating duplicate users when people sign in with different providers. How do I fix that?
Latest observation
This usually happens because you’re treating each provider account as a separate user instead of linking multiple login methods to one app user.
What to do
1) Use one internal user record
Create a single user in your database for each real person.
Then store external sign-in identities separately, for example:
userstable: your app’s user profileauth_identitiestable: one row per provider login
Example schema:
users
- id
- email
- name
- ...
auth_identities
- id
- user_id
- provider -- google, github, apple, etc.
- provider_user_id
- email
- created_at
A single user can have multiple auth_identities.
2) Link by a stable identifier, not just provider
When a user signs in:
- Look up the identity by:
providerprovider_user_id
- If found, log in that user.
- If not found:
- try to find an existing app user by verified email
- if found, attach this new identity to that user
- otherwise create a new user and identity
3) Be careful with email matching
Using email to merge accounts can be useful, but only if the email is verified by the provider.
Good practice:
- ✅ Safe to auto-link when provider says the email is verified
- ⚠️ Be cautious if email is unverified
- ❌ Don’t auto-link based on email alone for providers that don’t verify it reliably
4) Add a unique constraint
Prevent duplicates at the database level.
Example:
CREATE UNIQUE INDEX uniq_provider_identity
ON auth_identities(provider, provider_user_id);
Optionally also enforce one identity per provider per user if that’s your rule.
5) Support account linking in the UI
If a user already has an account and later signs in with GitHub/Google/Apple:
- ask them to confirm linking
- or link automatically only when you’re confident it’s the same person
This is especially useful if the provider emails differ.
Recommended sign-in flow
Sign in with provider
→ find identity by provider + provider_user_id
→ if exists: sign in user
→ else if verified email matches existing user:
link identity to that user
else:
create new user
create identity
Common mistake
A lot of apps do this:
- “Google user” → create user A
- “GitHub user” → create user B
even though both belong to the same person.
The fix is to separate authentication identities from app users.
If you want, I can help you design:
- a database schema
- a login/linking algorithm
- or code for your specific stack (NextAuth, Firebase, Auth0, Supabase, Django, Rails, etc.)