1- from typing import Annotated , Dict , Iterable , Optional
1+ from typing import Annotated , Dict , Iterable , List , Optional , TypedDict
22from dataclasses import dataclass , field
33from functools import cached_property
44
@@ -30,7 +30,7 @@ def user_validator(
3030 def valid_user_token (
3131 token_str : Annotated [str , Security (self .scheme )],
3232 required_scopes : security .SecurityScopes ,
33- ):
33+ ) -> TokenPayload :
3434 # Parse & validate token
3535 try :
3636 token = jwt .decode (
@@ -39,10 +39,10 @@ def valid_user_token(
3939 algorithms = ["RS256" ],
4040 audience = self .required_audience ,
4141 )
42- except jwt .exceptions .DecodeError as e :
42+ except jwt .exceptions .InvalidTokenError as e :
4343 raise HTTPException (
4444 status_code = status .HTTP_401_UNAUTHORIZED ,
45- detail = "Could not validate credentials" ,
45+ detail = f "Could not validate credentials: { e } " ,
4646 headers = {"WWW-Authenticate" : "Bearer" },
4747 ) from e
4848
@@ -97,3 +97,30 @@ def jwks_client(self):
9797 JWTs.
9898 """
9999 return jwt .PyJWKClient (f"{ self .internal_keycloak_api } /certs" )
100+
101+
102+ class RealmAccess (TypedDict ):
103+ roles : List [str ]
104+
105+
106+ class TokenPayload (TypedDict ):
107+ exp : int
108+ iat : int
109+ auth_time : int
110+ jti : str
111+ iss : str
112+ sub : str
113+ typ : str
114+ azp : str
115+ session_state : str
116+ acr : str
117+ allowed_origins : List [str ]
118+ realm_access : RealmAccess
119+ scope : str
120+ sid : str
121+ email_verified : bool
122+ name : str
123+ preferred_username : str
124+ given_name : str
125+ family_name : str
126+ email : str
0 commit comments