Django Allauth: Account Takeover via Provider Identifier Mutability
Table of Contents
“There’s always a side door.”
Overview#
I discovered an account takeover vulnerability in django-allauth, one of the most widely-used authentication libraries for Django. The vulnerability allows an attacker to impersonate arbitrary users by exploiting how certain OAuth providers’ identifiers are resolved.
Vulnerability Details#
CVE: CVE-2025-65431 Type: Improper Authentication / Account Takeover (CWE-287) Impact: Account Impersonation Affected Versions: django-allauth < 65.13.0
The Bug#
Both the Okta and NetIQ providers were using preferred_username as the identifier for third-party provider accounts. This value is mutable — users can change their preferred_username on the identity provider side.
This means:
- Victim authenticates via Okta/NetIQ, django-allauth stores
preferred_usernameas their provider UID - Attacker changes their own
preferred_usernameon the identity provider to match the victim’s stored value - Attacker authenticates — django-allauth matches them to the victim’s account
- Full account takeover
Why It Matters#
The core issue is using a mutable, user-controlled value for authorization decisions. OAuth providers typically expose multiple identifier fields:
| Field | Mutable | Safe for Auth |
|---|---|---|
sub (subject) | No | Yes |
email | Sometimes | Risky |
preferred_username | Yes | No |
The sub claim is the only identifier guaranteed to be immutable and unique per provider. Using anything else for account binding is a security anti-pattern.
Fix#
Fixed in django-allauth 65.13.0. The Okta and NetIQ providers now use immutable identifiers (sub) instead of preferred_username for account resolution.
References#
- CVE-2025-65431 — Snyk
- django-allauth Release Notes 65.3.1
- ZeroPath — django-allauth Account Takeover Vulnerabilities
Timeline#
| Date | Event |
|---|---|
| 2024 | Vulnerability discovered |
| 2024-12-25 | Fix released in django-allauth 65.3.1 |
| 2025 | CVE-2025-65431 assigned |
Responsible disclosure was followed.