55from fastapi import HTTPException , status
66from typing import Optional , Dict , Any
77import os
8- import jwt
8+ import jwt as pyjwt
99from datetime import datetime
1010from supabase import create_client , Client
1111
1212from services .observability import logger
13+ from services .exceptions import (
14+ AuthenticationError ,
15+ TokenExpiredError ,
16+ InvalidTokenError ,
17+ TokenMissingClaimError ,
18+ )
1319
1420
1521class SupabaseAuthService :
@@ -48,7 +54,7 @@ def verify_jwt(self, token: str) -> Dict[str, Any]:
4854 def _verify_local (self , token : str ) -> Dict [str , Any ]:
4955 """Decode and verify JWT locally with HS256 secret."""
5056 try :
51- payload = jwt .decode (
57+ payload = pyjwt .decode (
5258 token ,
5359 self .jwt_secret ,
5460 algorithms = ["HS256" ],
@@ -58,58 +64,40 @@ def _verify_local(self, token: str) -> Dict[str, Any]:
5864
5965 user_id = payload .get ("sub" )
6066 if not user_id :
61- raise HTTPException (
62- status_code = status .HTTP_401_UNAUTHORIZED ,
63- detail = "Token missing subject claim" ,
64- )
67+ raise TokenMissingClaimError ("sub" )
6568
6669 return {
6770 "user_id" : user_id ,
6871 "email" : payload .get ("email" ),
6972 "metadata" : payload .get ("user_metadata" ) or {},
7073 }
7174
72- except jwt .ExpiredSignatureError :
73- raise HTTPException (
74- status_code = status .HTTP_401_UNAUTHORIZED ,
75- detail = "Token expired" ,
76- )
77- except jwt .InvalidAudienceError :
78- raise HTTPException (
79- status_code = status .HTTP_401_UNAUTHORIZED ,
80- detail = "Invalid token audience" ,
81- )
82- except jwt .InvalidTokenError as e :
75+ except pyjwt .ExpiredSignatureError as e :
76+ raise TokenExpiredError ("Token expired" ) from e
77+ except pyjwt .InvalidAudienceError as e :
78+ raise InvalidTokenError ("Invalid token audience" ) from e
79+ except pyjwt .InvalidTokenError as e :
8380 logger .debug ("JWT decode failed" , error = str (e ))
84- raise HTTPException (
85- status_code = status .HTTP_401_UNAUTHORIZED ,
86- detail = "Invalid token" ,
87- )
81+ raise InvalidTokenError ("Invalid token" ) from e
8882
8983 def _verify_via_api (self , token : str ) -> Dict [str , Any ]:
9084 """Fallback: verify via Supabase API call (requires network)."""
9185 try :
9286 response = self .client .auth .get_user (token )
9387
9488 if not response .user :
95- raise HTTPException (
96- status_code = status .HTTP_401_UNAUTHORIZED ,
97- detail = "Invalid or expired token" ,
98- )
89+ raise InvalidTokenError ("Invalid or expired token" )
9990
10091 return {
10192 "user_id" : response .user .id ,
10293 "email" : response .user .email ,
10394 "metadata" : response .user .user_metadata or {},
10495 }
105- except HTTPException :
96+ except AuthenticationError :
10697 raise
10798 except Exception as e :
10899 logger .debug ("API-based JWT verification failed" , error = str (e ))
109- raise HTTPException (
110- status_code = status .HTTP_401_UNAUTHORIZED ,
111- detail = "Token verification failed" ,
112- )
100+ raise AuthenticationError ("Token verification failed" ) from e
113101
114102 async def signup (self , email : str , password : str , github_username : Optional [str ] = None ) -> Dict [str , Any ]:
115103 """
0 commit comments