Hamdy005 commited on
Commit
f55b5b5
Β·
1 Parent(s): 37bcb58

refactor: expand JWT algorithm support

Browse files
Files changed (3) hide show
  1. auth/routes.py +2 -20
  2. dependencies.py +16 -32
  3. main.py +1 -1
auth/routes.py CHANGED
@@ -350,7 +350,7 @@ async def exchange_session(request: Request, response: Response):
350
  payload = pyjwt.decode(
351
  raw_supabase_token,
352
  supabase_jwt_secret,
353
- algorithms=["HS256"],
354
  options={"verify_aud": False}, # Supabase uses 'authenticated' as aud
355
  )
356
  user_id = payload.get("sub")
@@ -358,26 +358,8 @@ async def exchange_session(request: Request, response: Response):
358
  user_metadata = payload.get("user_metadata", {})
359
  except pyjwt.ExpiredSignatureError:
360
  raise HTTPException(401, "Supabase token has expired. Please sign in again.")
361
- except pyjwt.InvalidTokenError as e:
362
- raise HTTPException(401, f"Invalid Supabase token: {e}")
363
- else:
364
- # Fallback: decode claims without signature verification if secret is not set
365
- try:
366
- import time
367
- payload = pyjwt.decode(
368
- raw_supabase_token,
369
- options={"verify_signature": False, "verify_aud": False},
370
- )
371
- exp = payload.get("exp")
372
- if exp and time.time() > exp:
373
- raise HTTPException(401, "Supabase token has expired. Please sign in again.")
374
- user_id = payload.get("sub")
375
- email = payload.get("email", "")
376
- user_metadata = payload.get("user_metadata", {})
377
- except HTTPException:
378
- raise
379
  except Exception:
380
- pass
381
 
382
  # Fallback: validate via Supabase API (slower, but works if unverified decoding failed)
383
  if not user_id:
 
350
  payload = pyjwt.decode(
351
  raw_supabase_token,
352
  supabase_jwt_secret,
353
+ algorithms=["HS256", "HS384", "HS512"],
354
  options={"verify_aud": False}, # Supabase uses 'authenticated' as aud
355
  )
356
  user_id = payload.get("sub")
 
358
  user_metadata = payload.get("user_metadata", {})
359
  except pyjwt.ExpiredSignatureError:
360
  raise HTTPException(401, "Supabase token has expired. Please sign in again.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  except Exception:
362
+ pass # Fall through to Supabase API validation below
363
 
364
  # Fallback: validate via Supabase API (slower, but works if unverified decoding failed)
365
  if not user_id:
dependencies.py CHANGED
@@ -88,27 +88,19 @@ async def get_current_user_id(request: Request) -> str:
88
  pass
89
 
90
  # ── Mode 1b: Supabase JWT stateless fallback (avoids 403 network race) ───
91
- try:
92
- if settings.supabase_jwt_secret:
93
  payload = pyjwt.decode(
94
  token,
95
  settings.supabase_jwt_secret,
96
- algorithms=["HS256"],
97
  options={"verify_aud": False},
98
  )
99
- else:
100
- payload = pyjwt.decode(
101
- token,
102
- options={"verify_signature": False, "verify_aud": False},
103
- )
104
- exp = payload.get("exp")
105
- if exp and time.time() > exp:
106
- payload = {}
107
- user_id = payload.get("sub")
108
- if user_id:
109
- return str(user_id)
110
- except Exception:
111
- pass
112
 
113
  # ── Mode 2: Supabase token (backwards-compat for Google OAuth sessions) ──
114
  try:
@@ -142,27 +134,19 @@ async def get_current_user(request: Request) -> Any:
142
  pass
143
 
144
  # ── Mode 1b: Supabase JWT stateless fallback ─────────────────────────────
145
- try:
146
- if settings.supabase_jwt_secret:
147
  payload = pyjwt.decode(
148
  token,
149
  settings.supabase_jwt_secret,
150
- algorithms=["HS256"],
151
  options={"verify_aud": False},
152
  )
153
- else:
154
- payload = pyjwt.decode(
155
- token,
156
- options={"verify_signature": False, "verify_aud": False},
157
- )
158
- exp = payload.get("exp")
159
- if exp and time.time() > exp:
160
- payload = {}
161
- user_id = payload.get("sub")
162
- if user_id:
163
- return {"id": user_id, "email": payload.get("email", "")}
164
- except Exception:
165
- pass
166
 
167
  # ── Mode 2: Supabase token (backwards compat) ────────────────────────────
168
  try:
 
88
  pass
89
 
90
  # ── Mode 1b: Supabase JWT stateless fallback (avoids 403 network race) ───
91
+ if settings.supabase_jwt_secret:
92
+ try:
93
  payload = pyjwt.decode(
94
  token,
95
  settings.supabase_jwt_secret,
96
+ algorithms=["HS256", "HS384", "HS512"],
97
  options={"verify_aud": False},
98
  )
99
+ user_id = payload.get("sub")
100
+ if user_id:
101
+ return str(user_id)
102
+ except Exception:
103
+ pass
 
 
 
 
 
 
 
 
104
 
105
  # ── Mode 2: Supabase token (backwards-compat for Google OAuth sessions) ──
106
  try:
 
134
  pass
135
 
136
  # ── Mode 1b: Supabase JWT stateless fallback ─────────────────────────────
137
+ if settings.supabase_jwt_secret:
138
+ try:
139
  payload = pyjwt.decode(
140
  token,
141
  settings.supabase_jwt_secret,
142
+ algorithms=["HS256", "HS384", "HS512"],
143
  options={"verify_aud": False},
144
  )
145
+ user_id = payload.get("sub")
146
+ if user_id:
147
+ return {"id": str(user_id), "email": payload.get("email", "")}
148
+ except Exception:
149
+ pass
 
 
 
 
 
 
 
 
150
 
151
  # ── Mode 2: Supabase token (backwards compat) ────────────────────────────
152
  try:
main.py CHANGED
@@ -95,7 +95,7 @@ app = FastAPI(
95
  title="AI Tutor API",
96
  description="Backend API for the AI Tutor for Students application",
97
  version="1.0.0",
98
- lifespan=lifespan,
99
  )
100
 
101
  @app.middleware("http")
 
95
  title="AI Tutor API",
96
  description="Backend API for the AI Tutor for Students application",
97
  version="1.0.0",
98
+ # lifespan=lifespan,
99
  )
100
 
101
  @app.middleware("http")