vectorplasticity commited on
Commit
0b0e0df
·
verified ·
1 Parent(s): 6adb94f

Fix auth loop: use TimestampSigner + base64 to match Starlette SessionMiddleware

Browse files
Files changed (1) hide show
  1. app/auth.py +22 -21
app/auth.py CHANGED
@@ -7,36 +7,37 @@ from fastapi import HTTPException, Request, status
7
  from starlette.middleware.sessions import SessionMiddleware
8
  from starlette.responses import JSONResponse, HTMLResponse
9
  from starlette.types import ASGIApp, Receive, Scope, Send
10
- from itsdangerous import URLSafeSerializer, BadSignature
 
 
11
  import secrets
12
  import time
13
  from typing import Optional, Callable
14
  from app.config import settings
15
 
16
 
17
- # Session serializer for decoding cookies in middleware
18
- # Must match Starlette's SessionMiddleware exactly
19
- def get_session_serializer():
20
- """Create a serializer matching SessionMiddleware's format exactly"""
21
- # Starlette uses URLSafeSerializer (not URLSafeTimedSerializer)
22
- # with these exact parameters
23
- return URLSafeSerializer(
24
- settings.SESSION_SECRET_KEY,
25
- salt="cookie-session",
26
- signer_kwargs={
27
- "key_derivation": "hmac",
28
- "digest_method": "sha1"
29
- }
30
- )
31
-
32
-
33
  def decode_session_cookie(cookie_value: str) -> dict:
34
- """Decode session cookie value to dictionary"""
 
 
 
 
 
35
  if not cookie_value:
36
  return {}
37
  try:
38
- serializer = get_session_serializer()
39
- return serializer.loads(cookie_value)
 
 
 
 
 
 
 
 
 
 
40
  except (BadSignature, Exception) as e:
41
  # Log error for debugging but don't crash
42
  print(f"Session decode error: {e}")
@@ -377,4 +378,4 @@ def get_login_html(error: str = None) -> str:
377
  document.getElementById('password').focus();
378
  </script>
379
  </body>
380
- </html>'''
 
7
  from starlette.middleware.sessions import SessionMiddleware
8
  from starlette.responses import JSONResponse, HTMLResponse
9
  from starlette.types import ASGIApp, Receive, Scope, Send
10
+ from itsdangerous import TimestampSigner, BadSignature
11
+ import base64
12
+ import json
13
  import secrets
14
  import time
15
  from typing import Optional, Callable
16
  from app.config import settings
17
 
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  def decode_session_cookie(cookie_value: str) -> dict:
20
+ """
21
+ Decode session cookie value to dictionary.
22
+ Must match Starlette's SessionMiddleware encoding exactly:
23
+ 1. TimestampSigner signs the data
24
+ 2. Data is base64 encoded JSON
25
+ """
26
  if not cookie_value:
27
  return {}
28
  try:
29
+ # Create the same signer that SessionMiddleware uses
30
+ signer = TimestampSigner(
31
+ settings.SESSION_SECRET_KEY,
32
+ salt="cookie-session"
33
+ )
34
+
35
+ # Unsign the cookie value
36
+ unsigned_value = signer.unsign(cookie_value)
37
+
38
+ # Decode base64 and parse JSON
39
+ decoded = base64.urlsafe_b64decode(unsigned_value)
40
+ return json.loads(decoded)
41
  except (BadSignature, Exception) as e:
42
  # Log error for debugging but don't crash
43
  print(f"Session decode error: {e}")
 
378
  document.getElementById('password').focus();
379
  </script>
380
  </body>
381
+ </html>'''