[SECURITY ADVISORY] Open Redirect in Login and Registration Flows via Unvalidated redirect Parameter
Title
Open Redirect Vulnerability via Unvalidated redirect Query Parameter in UserLoginFormAdmin and UserRegFormAdmin
Summary
An Open Redirect vulnerability (CWE-601) exists in fastapi-user-auth in the authentication and registration form handling logic.
The application retrieves the redirect query parameter from the HTTP request and utilizes it directly in server-side HTTP 307 Temporary Redirect responses and client-side form redirect attributes without validating the destination host or URL scheme.
An attacker can construct a crafted login or registration URL containing an arbitrary external target (e.g., https://evil.com), enticing users to authenticate and subsequently redirecting them to a malicious phishing site.
Vulnerability Details
-
Vulnerability Type: URL Redirection to Untrusted Site ('Open Redirect')
-
CWE ID: [CWE-601](https://cwe.mitre.org/data/definitions/601.html)
-
Severity: Medium (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N — Score: 6.1)
-
Affected Components:
fastapi_user_auth/admin/admin.py (UserLoginFormAdmin.get_form, UserLoginFormAdmin.route_page, UserRegFormAdmin.get_form)
Root Cause Analysis
In fastapi_user_auth/admin/admin.py, the redirect query parameter is read without any hostname or path validation:
1. Server-Side 307 Redirect (lines 127–134)
When an authenticated user visits the login page, the server issues an immediate HTTP 307 redirect using the unvalidated location header:
# fastapi_user_auth/admin/admin.py:127-134
@property
def route_page(self) -> Callable:
async def route(request: Request, result=Depends(super().route_page)):
if request.user:
raise HTTPException(
status_code=status.HTTP_307_TEMPORARY_REDIRECT,
detail="already logged in",
headers={"location": request.query_params.get("redirect") or "/"},
)
return result
return route
2. Client-Side Form Redirect (lines 118 & 190)
In both UserLoginFormAdmin.get_form and UserRegFormAdmin.get_form, the form redirect target is populated directly from user input:
# Line 118 (UserLoginFormAdmin) & Line 190 (UserRegFormAdmin)
form.redirect = request.query_params.get("redirect") or "/"
Because there is no check ensuring that the destination is relative (e.g., /dashboard) or restricted to a trusted whitelist of domains, external URLs such as https://evil.com or dangerous URI schemes (e.g., javascript:) are accepted.
Steps to Reproduce (Proof of Concept)
Scenario A: Server-Side 307 Redirection (Logged-in User)
- Log in to the application.
- Visit the following crafted URL:
GET /auth/login?redirect=https://evil.com HTTP/1.1
Host: target-app.com
- Observed Response
The browser immediately navigates to evil.com.
Scenario B: Post-Authentication Redirection (Unauthenticated User)
Send a victim a phishing link pointing to the legitimate site:
https://target-app.com/auth/login?redirect=https://evil.com/fake-login
The user sees a valid domain (target-app.com) and enters their legitimate credentials.
Upon successful submission, the client-side UI executes form.redirect and sends the user to:
https://evil.com/fake-login
Impact
Credential Harvesting / Phishing
Attackers can construct convincing phishing campaigns that leverage the legitimate domain's reputation to redirect victims to malicious sites.
Session / Token Exposure
If combined with browser quirks or token parameters, sensitive authentication context may be leaked in HTTP Referer headers.
Remediation / Suggested Patch
Implement URL validation to restrict redirects strictly to relative paths (same-origin):
--- a/fastapi_user_auth/admin/admin.py
+++ b/fastapi_user_auth/admin/admin.py
@@ -1,4 +1,5 @@
import contextlib
+from urllib.parse import urlparse
from typing import Any, Callable, Dict, List, Type
from fastapi import Depends, HTTPException
@@ -63,6 +64,15 @@ from fastapi_user_auth.mixins.admin import AuthFieldModelAdmin, AuthSelectModelA
+def _get_safe_redirect(url: str, default: str = "/") -> str:
+ """Validate redirect URL to ensure it is relative and does not redirect externally."""
+ if not url:
+ return default
+ parsed = urlparse(url)
+ if parsed.scheme or parsed.netloc:
+ return default
+ return url
+
class UserLoginFormAdmin(FormAdmin):
@@ -118,1 +128,1 @@ class UserLoginFormAdmin(FormAdmin):
- form.redirect = request.query_params.get("redirect") or "/"
+ form.redirect = _get_safe_redirect(request.query_params.get("redirect"))
@@ -132,1 +142,1 @@ class UserLoginFormAdmin.route_page:
- headers={"location": request.query_params.get("redirect") or "/"},
+ headers={"location": _get_safe_redirect(request.query_params.get("redirect"))},
@@ -190,1 +200,1 @@ class UserRegFormAdmin(UserRegFormAdmin):
- form.redirect = request.query_params.get("redirect") or "/"
+ form.redirect = _get_safe_redirect(request.query_params.get("redirect"))
---
[SECURITY ADVISORY] Open Redirect in Login and Registration Flows via Unvalidated
redirectParameterTitle
Open Redirect Vulnerability via Unvalidated
redirectQuery Parameter inUserLoginFormAdminandUserRegFormAdminSummary
An Open Redirect vulnerability (
CWE-601) exists infastapi-user-authin the authentication and registration form handling logic.The application retrieves the
redirectquery parameter from the HTTP request and utilizes it directly in server-side HTTP307 Temporary Redirectresponses and client-side form redirect attributes without validating the destination host or URL scheme.An attacker can construct a crafted login or registration URL containing an arbitrary external target (e.g.,
https://evil.com), enticing users to authenticate and subsequently redirecting them to a malicious phishing site.Vulnerability Details
Vulnerability Type: URL Redirection to Untrusted Site ('Open Redirect')
CWE ID: [CWE-601](https://cwe.mitre.org/data/definitions/601.html)
Severity: Medium (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N — Score: 6.1)
Affected Components:
fastapi_user_auth/admin/admin.py(UserLoginFormAdmin.get_form,UserLoginFormAdmin.route_page,UserRegFormAdmin.get_form)Root Cause Analysis
In
fastapi_user_auth/admin/admin.py, theredirectquery parameter is read without any hostname or path validation:1. Server-Side 307 Redirect (lines 127–134)
When an authenticated user visits the login page, the server issues an immediate HTTP 307 redirect using the unvalidated
locationheader:2. Client-Side Form Redirect (lines 118 & 190)
In both
UserLoginFormAdmin.get_formandUserRegFormAdmin.get_form, the form redirect target is populated directly from user input:Because there is no check ensuring that the destination is relative (e.g.,
/dashboard) or restricted to a trusted whitelist of domains, external URLs such ashttps://evil.comor dangerous URI schemes (e.g.,javascript:) are accepted.Steps to Reproduce (Proof of Concept)
Scenario A: Server-Side 307 Redirection (Logged-in User)
The browser immediately navigates to
evil.com.Scenario B: Post-Authentication Redirection (Unauthenticated User)
Send a victim a phishing link pointing to the legitimate site:
The user sees a valid domain (
target-app.com) and enters their legitimate credentials.Upon successful submission, the client-side UI executes
form.redirectand sends the user to:Impact
Credential Harvesting / Phishing
Attackers can construct convincing phishing campaigns that leverage the legitimate domain's reputation to redirect victims to malicious sites.
Session / Token Exposure
If combined with browser quirks or token parameters, sensitive authentication context may be leaked in HTTP Referer headers.
Remediation / Suggested Patch
Implement URL validation to restrict redirects strictly to relative paths (same-origin):