Agent Wranglers

Required

Link a provider login only to an account its owner controls

Never join a provider login to an existing account because the email addresses match. Link it after the person signs in to that account, or under the trusted-issuer exception below.

Risk if broken

An account or system taken over

Applies when

The project it has user accounts.

How to do it

When a new provider login carries the email of an existing account, sign the person in to nothing. Ask them to sign in the usual way, then connect the provider from settings. The one exception is a provider on your own list of issuers trusted for email, with email_verified true, when your account's email is verified too. OpenID Connect leaves the meaning of email_verified to each provider, so keep that list short and written down. Show every linked login in settings with its provider and the date it was added. This closes the takeover in stop strangers from claiming an address before its owner.

Examples

Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

JavaScript example

const ISSUERS_TRUSTED_FOR_EMAIL = new Set(['https://accounts.google.com']);

export function mayLinkByEmail(claims, existingUser) {
  return ISSUERS_TRUSTED_FOR_EMAIL.has(claims.iss)
    && claims.email_verified === true
    && existingUser.emailVerified === true;
}

Python example

ISSUERS_TRUSTED_FOR_EMAIL = {"https://accounts.google.com"}

def may_link_by_email(claims: dict, existing_user) -> bool:
    return (
        claims.get("iss") in ISSUERS_TRUSTED_FOR_EMAIL
        and claims.get("email_verified") is True
        and existing_user.email_verified
    )

How to check

On staging, sign in through a provider not on the trusted list, with the email of an existing account. No link is made and the sign-in page asks for the existing account. Repeat with email_verified false from a trusted issuer. No link is made either.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/accounts/sign-in-methods/link-provider-login">Agent Wranglers accounts playbook</a>. In code you write, add a comment next to it with the same link.