1
- from typing import Annotated , Dict , Iterable , Optional
1
+ from typing import Annotated , Dict , Iterable , List , Optional , TypedDict
2
2
from dataclasses import dataclass , field
3
3
from functools import cached_property
4
4
@@ -30,7 +30,7 @@ def user_validator(
30
30
def valid_user_token (
31
31
token_str : Annotated [str , Security (self .scheme )],
32
32
required_scopes : security .SecurityScopes ,
33
- ):
33
+ ) -> TokenPayload :
34
34
# Parse & validate token
35
35
try :
36
36
token = jwt .decode (
@@ -39,10 +39,10 @@ def valid_user_token(
39
39
algorithms = ["RS256" ],
40
40
audience = self .required_audience ,
41
41
)
42
- except jwt .exceptions .DecodeError as e :
42
+ except jwt .exceptions .InvalidTokenError as e :
43
43
raise HTTPException (
44
44
status_code = status .HTTP_401_UNAUTHORIZED ,
45
- detail = "Could not validate credentials" ,
45
+ detail = f "Could not validate credentials: { e } " ,
46
46
headers = {"WWW-Authenticate" : "Bearer" },
47
47
) from e
48
48
@@ -97,3 +97,30 @@ def jwks_client(self):
97
97
JWTs.
98
98
"""
99
99
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