[KongchangAI]
· 3 min read· 1,548 words

Three OAuth Account Takeovers: The Same-Origin Bug Turns Out to Be Automatic Email Linking

Three OAuth Account Takeovers: The Same-Origin Bug Turns Out to Be Automatic Email Linking

Three open-source projects suffered account takeover vulnerabilities because they trusted unverified emails to automatically link OAuth accounts.

The article discloses that Pingvin Share X, Better Auth, and AshAuthentication suffered OAuth account takeover due to the same logical flaw: when a user logs in via OAuth, the system obtains the email, and if a local account with the same email already exists, it automatically links them, assuming that "the OAuth provider's email verification" is equivalent to "proof of ownership of the local account." But an attacker only needs to register an email identical to the victim's on a provider that allows unverified emails and initiate an OAuth login to directly take over the victim's account. The article points out that the core principle of secure linking is never to automatically link solely because the emails are the same, and provides strategies such as requiring email_verified, separating registration and linking flows, using provider_user_id as the unique identifier, secondary confirmation, and audit logs, reminding developers to re-examine their OAuth linking logic.

Article Content

When OAuth login became mainstream, a seemingly convenient design—"automatically linking accounts by email"—is turning into an attacker's entry ticket. In three recently disclosed security incidents, three different open-source projects—Pingvin Share X, Better Auth, and AshAuthentication—all suffered from the same logical flaw, allowing a stranger's OAuth login to be bound to someone else's account.

The Essence of the Vulnerability: Trusting an Email That Should Not Be Trusted

What the three projects have in common is this: when a user logs in through an OAuth provider (such as Google or GitHub), the system retrieves the email address of that OAuth account and then searches its own database for an existing local account registered with the same email. If one is found, the OAuth identity is directly merged with the local account without additional verification.

The problem with this flow is that it assumes "the OAuth provider's email verification" is equivalent to "proof of ownership of the local account." But that is not the case. If an attacker can control an OAuth account with the same email as the victim's—for example, on some providers, users can first register an unverified email, or exploit differences in email verification across providers—the attacker can log in via OAuth and directly take over the victim's local account.

According to security analysis articles, the specific point of failure differs slightly for each project, but the root cause is the same: an incorrect trust boundary in the decision to "automatically link by email."

The Trust Model of OAuth 2.0 and OpenID Connect

OAuth 2.0 itself is an authorization framework, not an identity authentication protocol. Its design goal is to let third-party applications access protected resources under user authorization, and its core output is an access token, not a reliable assertion of "who the user is." What the article discusses as "OAuth login" is actually usually built on top of OpenID Connect (OIDC), which adds an identity layer on top of OAuth 2.0 and returns claims such as sub (subject, the provider's unique user identifier), email, and email_verified through an ID Token (a JWT).

Understanding this distinction is crucial for analyzing the vulnerability: email is merely an attribute declared by the provider and may be unverified, whereas email_verified indicates that the provider has confirmed that the email is controlled by the current user. Meanwhile, sub or provider_user_id is the stable and difficult-to-forge identity identifier. Using email as a primary key for account linking is essentially mistaking a mutable, forgeable attribute for an identity credential.

In addition, different providers vary greatly in their email verification requirements: Google typically requires verification before login, while some self-hosted or niche providers' OIDC implementations allow users to set arbitrary unverified emails. It is precisely this inconsistency in verification policies across providers that gives attackers an opportunity.

The Specific Paths of the Three Incidents

Pingvin Share X: The scenario is that an attacker registers with an OAuth provider using an unverified email (the same as the victim's local account email), then initiates an OAuth login. Because the system does not require the email to be verified, the attacker's OAuth identity is directly linked to the victim's account, completing the takeover.

Better Auth: The problem is that it trusts the email field returned by the OAuth provider but does not confirm whether that email has been verified by the provider. If the provider allows setting an unverified email, the attacker can exploit this.

AshAuthentication: It may fail to distinguish between the "new user registration" and "existing account linking" flows when handling OAuth callbacks, allowing an attacker to force linking.

These three incidents are not isolated. They reflect a widespread security blind spot in the open-source ecosystem: developers tend to simplify the login flow but overlook the attack surface of account takeover.

Why "Account Takeover" Is More Dangerous Than an Ordinary Vulnerability

Account takeover (ATO) differs from a data breach: it gives the attacker full control over the victim's account—including reading private data, posting content as the victim, changing passwords, and even laterally penetrating other services associated with the victim on that platform. Because many users reuse emails or even passwords across different sites, a single ATO can trigger a chain reaction.

In the scenario of automatic OAuth email linking, the threshold for triggering ATO is often extremely low: the attacker does not need to crack a password or phish; they only need to register an email address identical to the victim's on some provider that allows unverified emails and initiate an OAuth login to complete the takeover. This attack does not depend on any interaction from the victim and is highly stealthy; the victim may have their account fully controlled without any awareness. Because the attacker logs in "normally" through the legitimate OAuth flow, anomalies are often invisible in the logs, which is also why such vulnerabilities are particularly difficult to detect.

How Secure OAuth Linking Should Be Done

To avoid similar account takeovers, the core principle is: never automatically link accounts solely because the emails are the same. The following are several feasible security strategies:

  1. Require verified email: In the OAuth callback, check the email_verified field returned by the provider (if supported). Only allow verified emails to trigger linking.

  2. Separate registration and linking: When a new user logs in via OAuth, create a new account; linking to an existing account must go through an independent verification step, such as sending a confirmation link to the local account's email, or requiring the user to first log in to the local account and then bind OAuth.

  3. Use the OAuth provider's unique ID: When linking, prioritize the combination of provider + provider_user_id rather than email. Email can be used as auxiliary information, but not as a unique identifier.

  4. Secondary confirmation: If an existing email is detected, do not automatically link it; instead, prompt the user, "This email is already registered; please log in and bind it," or send a verification email.

  5. Auditing and logging: Record all OAuth linking operations to facilitate post-incident tracing.

What Is the provider + provider_user_id Composite Identifier?

In practice, provider_user_id corresponds to the sub claim in the OIDC specification, a string assigned by the OAuth/OpenID provider to each user that is unique and stable within that provider. The key difference from email is that email can be changed by the user and may be unverified, whereas sub is generated by the provider when the user creates the account, does not change when the email changes, and cannot be taken over by a different user.

Therefore, the correct approach for secure linking is: the server stores a table that maps the local account using (provider, sub) as the unique key. When a user logs in through a provider for the first time, this combination is used to look up an existing binding; if none exists, the user is treated as new. Email can only be used as display information or as an auxiliary matching condition, and must never be used alone for account merging.

It should be noted that the same user has different sub values on Google and GitHub, so sub cannot be compared across providers and can only be stored separately by provider. If it is truly necessary to merge the same person's accounts across providers, this must rely on a secondarily verified email or a user-initiated binding operation, and cannot be merged merely because the strings are identical.

Implications for Developers

These three cases sound a warning for all developers involved in OAuth login. Although automatic email linking improves user experience, the cost may be catastrophic account takeover. Between security and convenience, the right trade-off must be made.

For teams using open-source authentication libraries, it is recommended to immediately check their own OAuth linking logic: Are they trusting unverified emails? Do they distinguish registration from linking? Do they require additional verification when linking?

According to discussions in the security community, many mainstream OAuth providers (such as Google) return the email_verified field, but not all providers enforce email verification. Developers need to formulate corresponding strategies based on the characteristics of the providers they use.

Ultimately, secure OAuth account linking is not "merge if the emails are the same," but "merge only after verifying ownership."

One-line Summary

Three open-source projects suffered account takeover vulnerabilities because they trusted unverified emails to automatically link OAuth accounts.

Paragraph Summary

The article discloses that three open-source projects—Pingvin Share X, Better Auth, and AshAuthentication—suffered from OAuth account takeover due to the same logical flaw: when a user logs in via OAuth, the system obtains the email, and if a local account with the same email already exists, it automatically links them, assuming that "the OAuth provider's email verification" is equivalent to "proof of ownership of the local account." But an attacker only needs to register an email identical to the victim's on a provider that allows unverified emails and initiate an OAuth login to directly take over the victim's account. The article points out that the core principle of secure linking is never to automatically link solely because the emails are the same, and provides strategies such as requiring email_verified, separating registration and linking flows, using provider_user_id as the unique identifier, secondary confirmation, and audit logs, reminding developers to re-examine their OAuth linking logic.

#OAuth account takeover#email auto-linking vulnerability#email_verified#provider_user_id#open-source authentication security#account takeover
Share:

Related articles