Skip to main content

authdrift

Find OAuth handlers that will break when users rename their Gmail.

On 31 March 2026, Google began letting users rename their primary Gmail address. Every OAuth integration that uses email as the user lookup key will silently create a duplicate account when a user renames. Most do.

authdrift is a static analysis tool that scans your codebase for the exact patterns that explode on a Gmail rename — and on the ~0.04% baseline sub-claim drift Truffle Security documented in January 2025.

Install

pip install authdrift

Requires semgrep (installed automatically).

Use

authdrift scan ./

Example output:

src/auth/google.ts
   12:18  WARNING  oauth-passport-email-as-primary-key
            This OAuth handler is using `profile.emails[0].value` as a user lookup key.
            When a user renames their Gmail address, this lookup will fail and your
            application will silently create a duplicate user record.
            Fix: use `profile.id` (the OIDC `sub` claim) as the immutable primary key.

JSON output for CI:

authdrift scan ./ --json

Why this matters

Atlassian's own KB confirms that SCIM email changes create duplicate Atlassian Cloud accounts. Google's developer documentation acknowledges that revoke + reauth produces duplicate accounts. The cascade is documented; the fix is not deployed.

authdrift flags the exact code patterns that produce phantom users after a rename event. Three rules, narrowly scoped, designed to slot into CI alongside semgrep, trufflehog, and gitleaks without producing noise.

What it catches today

  • Passport.js handlers using profile.emails[0].value as a user lookup key (passport-google-oauth20, passport-google-oauth2)
  • NextAuth signIn callbacks resolving users by user.email against Prisma
  • Python (Django / SQLAlchemy) handlers querying by userinfo['email'] from Google's userinfo response

What it deliberately does NOT do

  • Flag every reference to email in an OAuth file. The rules require the email value to be used as a lookup key, not just read or logged.
  • Flag handlers that key on sub / profile.id and use email only as a contact attribute.
  • Auto-fix anything. Read-only by design.

Roadmap

  • More OAuth library coverage (lucia-auth, authlib, omniauth, Clerk, Supabase Auth, Firebase Auth)
  • A --fix mode that suggests the sub-keyed equivalent
  • A hosted scan for organisations that can't run a CLI

License

MIT.

Metadata

Release files for authdrift 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for authdrift 0.1.0
File Size Uploaded Provenance Actions
authdrift-0.1.0.tar.gz 5.6 kB Without provenance Details for authdrift-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for authdrift 0.1.0
File Interpreter ABI Platform Actions
authdrift-0.1.0-py3-none-any.whl Python 3 none any Details for authdrift-0.1.0-py3-none-any.whl

Total release size: 11.7 kB

Release files / authdrift-0.1.0.tar.gz

Download URL authdrift-0.1.0.tar.gz
Size 5.6 kB
Tags Source
SHA-256 checksum
How to use checksums
7f307e8d502d0cacd26709d5efaeaded1eae11a872da5353df192fc72de4ea02
BLAKE2b-256 checksum
How to use checksums
21ea69d253f0c524a9cc762804d4317df425222566cee800e3a4f0ebc2f5ca9b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release files / authdrift-0.1.0-py3-none-any.whl

Download URL authdrift-0.1.0-py3-none-any.whl
Size 6.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
184235c73dcc25a3ea1b8f5a7d11a7a8b2ccab6f8cfb044f05e6581b756131f5
BLAKE2b-256 checksum
How to use checksums
78d013defebef5e2b18fdbf03d7f3480a933bca38762b3c59db107873a7d18b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Security for authdrift 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page