Prompt
Can you help me troubleshoot a login flow where users sign in with Google but don’t get linked to existing accounts?
Latest observation
Yes — I can help. This usually comes down to one of a few issues in the identity-linking flow.
Common reasons Google sign-in doesn’t link to an existing account
1) The app is treating Google sign-in as a brand-new user every time
If your auth logic creates a new user record on successful Google OAuth without first checking for an existing account, linking won’t happen.
Check for:
- Whether you search by email before creating a new user
- Whether you have a separate “link identity” step
- Whether the app uses provider-specific user IDs only
2) Email mismatch or missing email
Linking often relies on matching the Google email to an existing local account.
Watch out for:
- Google account email differs from the user’s existing account email
- The Google scope doesn’t include
email - Email is not verified or not returned by the provider
- Existing account uses another email/alias
3) Automatic linking is intentionally disabled
Many systems avoid auto-linking because it can be a security risk.
Examples:
- The user must first sign into the existing account, then connect Google in settings
- The provider only links after explicit consent
- “Match by email” is off by default
4) Duplicate accounts already exist
If a user previously signed up with Google and also with email/password, there may already be two separate accounts.
Check:
- Same email, but different internal user IDs
- Existing provider identity record not attached to the local account
- Historical migrations created duplicates
5) Google account identity data isn’t being persisted correctly
Your callback may receive the Google profile correctly, but the DB write to the link table fails.
Check for:
- Errors in the OAuth callback logs
- Unique constraint violations
- Race conditions during account creation
- Missing transaction / partial write
6) Your provider configuration is incomplete
If the OAuth client or app config is wrong, you may get limited profile data.
Verify:
- Correct client ID/secret
- Correct redirect URI
- Scopes include at least
openid email profile - Google consent screen and project settings are valid
7) Your auth library requires explicit account linking
Some libraries do not auto-link by design.
Examples:
- Auth0
- Firebase Auth
- NextAuth / Auth.js
- Supabase Auth
- Cognito
- Passport.js setups
In many cases, you must implement linking rules yourself.
What to inspect first
In your login callback, log:
- Google provider user ID (
sub) - Email returned from Google
- Whether email is verified
- Existing user lookup result
- Whether link/create code path ran
- Any DB errors during save
Pseudocode for safe linking
const googleUser = getGoogleProfile();
const email = googleUser.email;
let account = await findAccountByEmail(email);
if (account) {
await linkGoogleIdentity(account.id, googleUser.sub);
} else {
account = await createNewAccount({
email,
googleSub: googleUser.sub
});
}
If you already do this, confirm:
findAccountByEmail()is actually returning the row you expectlinkGoogleIdentity()writes to the correct table- there isn’t another step later that overwrites the account ID
Security note
Auto-linking by email can be risky unless the email is verified and you trust the provider’s identity guarantees. A safer pattern is:
- User signs into the existing account
- User explicitly connects Google from account settings
If you want, I can help you debug the exact flow
Send me any of these and I’ll narrow it down:
- Your auth stack/library
- Callback code
- Database schema for users/identities
- Sample logs from a failing login
- Whether you want auto-linking or explicit linking