11import json
22from collections .abc import Iterable
33from datetime import timedelta
4+ from functools import cached_property
45from typing import Any , Optional , Union
56
67import jwt
@@ -64,6 +65,21 @@ def __init__(
6465 self .leeway = leeway
6566 self .json_encoder = json_encoder
6667
68+ @cached_property
69+ def prepared_signing_key (self ) -> Any :
70+ return self ._prepare_key (self .signing_key )
71+
72+ @cached_property
73+ def prepared_verifying_key (self ) -> Any :
74+ return self ._prepare_key (self .verifying_key )
75+
76+ def _prepare_key (self , key : Optional [str ]) -> Any :
77+ # Support for PyJWT 1.7.1 or empty signing key
78+ if key is None or not getattr (jwt .PyJWS , "get_algorithm_by_name" , None ):
79+ return key
80+ jws_alg = jwt .PyJWS ().get_algorithm_by_name (self .algorithm )
81+ return jws_alg .prepare_key (key )
82+
6783 def _validate_algorithm (self , algorithm : str ) -> None :
6884 """
6985 Ensure that the nominated algorithm is recognized, and that cryptography is installed for those
@@ -98,17 +114,17 @@ def get_leeway(self) -> timedelta:
98114 )
99115 )
100116
101- def get_verifying_key (self , token : Token ) -> Optional [ str ] :
117+ def get_verifying_key (self , token : Token ) -> Any :
102118 if self .algorithm .startswith ("HS" ):
103- return self .signing_key
119+ return self .prepared_signing_key
104120
105121 if self .jwks_client :
106122 try :
107123 return self .jwks_client .get_signing_key_from_jwt (token ).key
108124 except PyJWKClientError as ex :
109125 raise TokenBackendError (_ ("Token is invalid" )) from ex
110126
111- return self .verifying_key
127+ return self .prepared_verifying_key
112128
113129 def encode (self , payload : dict [str , Any ]) -> str :
114130 """
@@ -122,7 +138,7 @@ def encode(self, payload: dict[str, Any]) -> str:
122138
123139 token = jwt .encode (
124140 jwt_payload ,
125- self .signing_key ,
141+ self .prepared_signing_key ,
126142 algorithm = self .algorithm ,
127143 json_encoder = self .json_encoder ,
128144 )
0 commit comments