Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2025-64521

CVE-2025-64521: Goauthentik Authentik Auth Bypass Vulnerability

CVE-2025-64521 is an authentication bypass flaw in Goauthentik Authentik that allows deactivated service accounts to authenticate via OAuth. This post explains the technical details, affected versions, and mitigation steps.

Published:

CVE-2025-64521 Overview

CVE-2025-64521 affects authentik, an open-source Identity Provider (IdP). The vulnerability allows deactivated service accounts to authenticate against OAuth providers using client_id and client_secret credentials. When applications authenticate via the OAuth2 client credentials flow, authentik automatically creates a backing service account for the provider. Prior to the fixed releases, this service account remained usable even after an administrator deactivated it. The flaw is categorized under CWE-289: Authentication Bypass by Alternate Name/Path. Versions 2025.8.5 and 2025.10.2 remediate the issue.

Critical Impact

Deactivated service accounts retain OAuth2 authentication capability, allowing continued access to protected applications when administrators believed the account was disabled.

Affected Products

  • goauthentik authentik versions prior to 2025.8.5
  • goauthentik authentik versions prior to 2025.10.2
  • Applications relying on authentik OAuth2 provider client credentials grant

Discovery Timeline

  • 2025-11-19 - CVE-2025-64521 published to NVD
  • 2026-06-17 - Last updated in NVD database

Technical Details for CVE-2025-64521

Vulnerability Analysis

The vulnerability resides in authentik's OAuth2 token endpoint handling. When a client authenticates using the client_credentials grant type, authentik resolves the associated service account user before issuing an access token. The lookup did not verify the account's active state, allowing deactivated accounts to receive valid tokens. Other authorization surfaces such as policy evaluation and federation still honored the account state correctly. Only the direct authentication path failed to enforce the is_active flag, producing an inconsistency between administrative intent and runtime behavior.

Root Cause

The root cause is missing state validation in the user resolution logic within authentik/providers/oauth2/views/token.py. The User.objects.filter(username=username) query returned any user matching the supplied identifier regardless of activation status. Accounts flagged inactive via is_active=False were treated identically to active accounts during the token issuance flow.

Attack Vector

An attacker who previously obtained valid client_id and client_secret values for an application can continue to obtain access tokens after an administrator deactivates the corresponding service account. Exploitation requires high privileges to have originally acquired the credentials and user interaction context around policy configuration. The scope changes because the issued token grants access to downstream applications trusting authentik.

python
# Security patch in authentik/providers/oauth2/views/token.py
     self, request: HttpRequest, username: str, password: str
 ):
     # Authenticate user based on credentials
-    user = User.objects.filter(username=username).first()
+    user = User.objects.filter(username=username, is_active=True).first()
     if not user:
         raise TokenError("invalid_grant")
     token: Token = Token.filter_not_expired(
# Source: https://github.com/goauthentik/authentik/commit/9dbdfc3f1be0f1be36f8efce2442897b2a54a71c

The fix adds is_active=True to the user lookup, ensuring deactivated accounts cannot resolve to a valid identity during token issuance.

Detection Methods for CVE-2025-64521

Indicators of Compromise

  • Successful OAuth2 token issuance events for service accounts marked inactive in the authentik admin interface.
  • Access log entries at /application/o/token/ containing client_id values tied to deactivated providers.
  • Downstream application sessions established by principals whose authentik account status is is_active=False.

Detection Strategies

  • Correlate authentik audit events for account deactivation with subsequent token_issued events for the same subject.
  • Query the authentik database to enumerate AuthenticatedSession or AccessToken records referencing users where is_active=False.
  • Compare provider-linked service account status against recent client_credentials grant activity to identify state drift.

Monitoring Recommendations

  • Forward authentik application and event logs to a centralized SIEM for retention and correlation.
  • Alert on any OAuth2 grant issued to a user whose deactivation timestamp precedes the token issuance timestamp.
  • Monitor for anomalous volumes of client_credentials flows following administrative offboarding actions.

How to Mitigate CVE-2025-64521

Immediate Actions Required

  • Upgrade authentik to version 2025.8.5 or 2025.10.2 as published in the GitHub Security Advisory GHSA-xr73-jq5p-ch8r.
  • Rotate client_secret values for any OAuth2 provider whose backing service account has been deactivated.
  • Audit existing access tokens and revoke sessions tied to inactive service accounts.

Patch Information

The fix is delivered in authentik 2025.8.5 and 2025.10.2. The change adds is_active=True filtering to the user resolution query in authentik/providers/oauth2/views/token.py. Review the upstream commit for the exact modification.

Workarounds

  • Attach an application-level policy that explicitly validates the service account's active state and denies access when the account is disabled.
  • Delete rather than deactivate service accounts that must lose all access, removing the resolvable identity entirely.
  • Restrict issuance of client_id and client_secret credentials to a minimal set of administrators tracked in change management.
bash
# Verify authentik version after upgrade
docker exec authentik-server ak version

# Confirm patched behavior: token request for a deactivated account should fail
curl -X POST https://authentik.example.com/application/o/token/ \
  -d "grant_type=client_credentials" \
  -d "client_id=<CLIENT_ID>" \
  -d "client_secret=<CLIENT_SECRET>"
# Expected response after patch: {"error":"invalid_grant"}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.