Skip to content

Google OAuth: email-based user lookup may create duplicate accounts after Gmail rename #882

@Neelagiri65

Description

@Neelagiri65

Hey. Heads up on something I found while researching the impact of Google's Gmail rename feature on NextAuth apps.

What changed

Google shipped Gmail address renaming on 31 March 2026. After a rename plus token revocation the NextAuth callback receives the new email. Google's own docs confirm this produces duplicate accounts in apps keying on email.

What I found

The NextAuth configuration in ztnet uses email for user identification in the sign-in flow. After a Gmail rename, if the email Google returns no longer matches the stored user record, the user either can't sign in or a new account gets created. For a network controller this means losing access to ZeroTier network configuration. Not great.

My recommendation

NextAuth provides the providerAccountId (Google's sub claim) through the account callback. I'd recommend using that as the primary identifier:

// In auth config
callbacks: {
  async signIn({ user, account }) {
    // Look up by providerAccountId first
    const existing = await prisma.account.findFirst({
      where: {
        provider: account.provider,
        providerAccountId: account.providerAccountId,
      },
    });
    // Link or create based on stable ID
  }
}

For reference, cal.com is also a NextAuth project and they handle this by using token.sub as the primary identity key. Worth looking at their implementation as a reference.

Context

I found this pattern across 124 public repos in a code audit. Full writeup: Google Externalised the Cost of Renaming Gmail

I built authdrift, a Semgrep scanner that catches the email-keying pattern across NextAuth, Passport.js, Python/Django, Ruby/OmniAuth codebases. Might be useful for checking other auth paths.

Happy to help with a fix or provide more detail. Let me know.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions