77import logging
88from datetime import timedelta
99from typing import Optional
10- from urllib .parse import urlencode
10+ from urllib .parse import urlencode , urlparse
1111from fastapi import APIRouter , HTTPException , Query , Request
1212from fastapi .responses import RedirectResponse , JSONResponse , HTMLResponse
1313from pydantic import BaseModel
2020router = APIRouter ()
2121
2222
23+ def is_safe_redirect_url (url : Optional [str ]) -> bool :
24+ """
25+ Vérifie qu'une URL de redirection est sûre (relative ou sans domaine externe).
26+
27+ Security: CWE-601 - Prevent open redirect vulnerabilities
28+ """
29+ if not url :
30+ return True
31+
32+ # Remove backslashes that could bypass urlparse
33+ url = url .replace ('\\ ' , '' )
34+
35+ parsed = urlparse (url )
36+
37+ # URL must not have a network location (domain) or scheme (http://, https://, etc.)
38+ # This ensures only relative paths are allowed
39+ if parsed .netloc or parsed .scheme :
40+ return False
41+
42+ return True
43+
44+
2345class TokenResponse (BaseModel ):
2446 """Réponse contenant le JWT."""
2547 access_token : str
@@ -44,6 +66,10 @@ async def login(redirect_uri: Optional[str] = Query(None, description="Optional
4466 if not auth_config .is_enabled or not auth_config .has_provider (AuthProvider .OIDC ):
4567 raise HTTPException (status_code = 400 , detail = "OIDC authentication is not configured" )
4668
69+ # Validate redirect_uri to prevent open redirect attacks (CWE-601)
70+ if redirect_uri and not is_safe_redirect_url (redirect_uri ):
71+ raise HTTPException (status_code = 400 , detail = "Invalid redirect URI: external URLs not allowed" )
72+
4773 config = auth_config .get_oidc_config ()
4874 callback_uri = redirect_uri or os .getenv ("OIDC_API_REDIRECT_URI" , "http://localhost:8080/api/auth/callback" )
4975 auth_params = {
@@ -68,6 +94,10 @@ async def callback(
6894 if not auth_config .has_provider (AuthProvider .OIDC ):
6995 raise HTTPException (status_code = 400 , detail = "OIDC authentication is not configured" )
7096
97+ # Validate redirect_uri to prevent open redirect attacks (CWE-601)
98+ if redirect_uri and not is_safe_redirect_url (redirect_uri ):
99+ raise HTTPException (status_code = 400 , detail = "Invalid redirect URI: external URLs not allowed" )
100+
71101 callback_uri = redirect_uri or os .getenv ("OIDC_API_REDIRECT_URI" , "http://localhost:8080/api/auth/callback" )
72102 token_data = await oidc_client .exchange_code_for_token (code , callback_uri )
73103 if not token_data :
0 commit comments