1616
1717
1818class PyJWT (object ):
19- def __init__ (self , algorithms = None ):
19+ def __init__ (self , algorithms = None , options = None ):
2020 self ._algorithms = get_default_algorithms ()
2121 self ._valid_algs = set (algorithms ) if algorithms is not None else set (self ._algorithms )
2222
@@ -25,6 +25,19 @@ def __init__(self, algorithms=None):
2525 if key not in self ._valid_algs :
2626 del self ._algorithms [key ]
2727
28+ if not options :
29+ options = {}
30+
31+ self .default_options = {
32+ 'verify_signature' : True ,
33+ 'verify_exp' : True ,
34+ 'verify_nbf' : True ,
35+ 'verify_iat' : True ,
36+ 'verify_aud' : True ,
37+ }
38+
39+ self .options = self ._merge_options (self .default_options , options )
40+
2841 def register_algorithm (self , alg_id , alg_obj ):
2942 """
3043 Registers a new Algorithm for use when creating and verifying tokens.
@@ -110,14 +123,16 @@ def encode(self, payload, key, algorithm='HS256', headers=None, json_encoder=Non
110123
111124 return b'.' .join (segments )
112125
113- def decode (self , jwt , key = '' , verify = True , algorithms = None , ** kwargs ):
126+ def decode (self , jwt , key = '' , verify = True , algorithms = None , options = None , ** kwargs ):
114127 payload , signing_input , header , signature = self ._load (jwt )
115128
116129 if verify :
117- self ._verify_signature (payload , signing_input , header , signature ,
118- key , algorithms )
130+ merged_options = self ._merge_options (override_options = options )
131+ if merged_options .get ('verify_signature' ):
132+ self ._verify_signature (payload , signing_input , header , signature ,
133+ key , algorithms )
119134
120- self ._validate_claims (payload , ** kwargs )
135+ self ._validate_claims (payload , options = merged_options , ** kwargs )
121136
122137 return payload
123138
@@ -177,8 +192,8 @@ def _verify_signature(self, payload, signing_input, header, signature,
177192 except KeyError :
178193 raise InvalidAlgorithmError ('Algorithm not supported' )
179194
180- def _validate_claims (self , payload , verify_expiration = True , leeway = 0 ,
181- audience = None , issuer = None ):
195+ def _validate_claims (self , payload , audience = None , issuer = None , leeway = 0 ,
196+ options = None , ** kwargs ):
182197 if isinstance (leeway , timedelta ):
183198 leeway = timedelta_total_seconds (leeway )
184199
@@ -187,7 +202,7 @@ def _validate_claims(self, payload, verify_expiration=True, leeway=0,
187202
188203 now = timegm (datetime .utcnow ().utctimetuple ())
189204
190- if 'iat' in payload :
205+ if 'iat' in payload and options . get ( 'verify_iat' ) :
191206 try :
192207 iat = int (payload ['iat' ])
193208 except ValueError :
@@ -196,7 +211,7 @@ def _validate_claims(self, payload, verify_expiration=True, leeway=0,
196211 if iat > (now + leeway ):
197212 raise InvalidIssuedAtError ('Issued At claim (iat) cannot be in the future.' )
198213
199- if 'nbf' in payload and verify_expiration :
214+ if 'nbf' in payload and options . get ( 'verify_nbf' ) :
200215 try :
201216 nbf = int (payload ['nbf' ])
202217 except ValueError :
@@ -205,7 +220,7 @@ def _validate_claims(self, payload, verify_expiration=True, leeway=0,
205220 if nbf > (now + leeway ):
206221 raise ImmatureSignatureError ('The token is not yet valid (nbf)' )
207222
208- if 'exp' in payload and verify_expiration :
223+ if 'exp' in payload and options . get ( 'verify_exp' ) :
209224 try :
210225 exp = int (payload ['exp' ])
211226 except ValueError :
@@ -214,7 +229,7 @@ def _validate_claims(self, payload, verify_expiration=True, leeway=0,
214229 if exp < (now - leeway ):
215230 raise ExpiredSignatureError ('Signature has expired' )
216231
217- if 'aud' in payload :
232+ if 'aud' in payload and options . get ( 'verify_aud' ) :
218233 audience_claims = payload ['aud' ]
219234 if isinstance (audience_claims , string_types ):
220235 audience_claims = [audience_claims ]
@@ -233,6 +248,21 @@ def _validate_claims(self, payload, verify_expiration=True, leeway=0,
233248 if payload .get ('iss' ) != issuer :
234249 raise InvalidIssuerError ('Invalid issuer' )
235250
251+ def _merge_options (self , default_options = None , override_options = None ):
252+ if not default_options :
253+ default_options = {}
254+
255+ if not override_options :
256+ override_options = {}
257+
258+ try :
259+ merged_options = self .default_options .copy ()
260+ merged_options .update (override_options )
261+ except (AttributeError , ValueError ) as e :
262+ raise TypeError ('options must be a dictionary: %s' % e )
263+
264+ return merged_options
265+
236266
237267_jwt_global_obj = PyJWT ()
238268encode = _jwt_global_obj .encode
0 commit comments