5
5
import pytest
6
6
7
7
from jose import jws , jwt
8
+ from jose .constants import ALGORITHMS
8
9
from jose .exceptions import JWTError , JWKError
9
10
10
11
@@ -56,7 +57,7 @@ def test_no_alg(self, claims, key):
56
57
],
57
58
)
58
59
def test_numeric_key (self , key , token ):
59
- token_info = jwt .decode (token , key )
60
+ token_info = jwt .decode (token , key , algorithms = ALGORITHMS . SUPPORTED )
60
61
assert token_info == {"name" : "test" }
61
62
62
63
def test_invalid_claims_json (self ):
@@ -108,7 +109,7 @@ def test_no_alg_default_headers(self, claims, key, headers):
108
109
109
110
def test_non_default_headers (self , claims , key , headers ):
110
111
encoded = jwt .encode (claims , key , headers = headers )
111
- decoded = jwt .decode (encoded , key )
112
+ decoded = jwt .decode (encoded , key , algorithms = ALGORITHMS . HS256 )
112
113
assert claims == decoded
113
114
all_headers = jwt .get_unverified_headers (encoded )
114
115
for k , v in headers .items ():
@@ -159,7 +160,7 @@ def test_encode(self, claims, key):
159
160
def test_decode (self , claims , key ):
160
161
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" ".eyJhIjoiYiJ9" ".jiMyrsmD8AoHWeQgmxZ5yq8z0lXS67_QGs52AzC8Ru8"
161
162
162
- decoded = jwt .decode (token , key )
163
+ decoded = jwt .decode (token , key , algorithms = ALGORITHMS . SUPPORTED )
163
164
164
165
assert decoded == claims
165
166
@@ -190,31 +191,31 @@ def test_leeway_is_timedelta(self, claims, key):
190
191
options = {"leeway" : leeway }
191
192
192
193
token = jwt .encode (claims , key )
193
- jwt .decode (token , key , options = options )
194
+ jwt .decode (token , key , options = options , algorithms = ALGORITHMS . HS256 )
194
195
195
196
def test_iat_not_int (self , key ):
196
197
claims = {"iat" : "test" }
197
198
198
199
token = jwt .encode (claims , key )
199
200
200
201
with pytest .raises (JWTError ):
201
- jwt .decode (token , key )
202
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
202
203
203
204
def test_nbf_not_int (self , key ):
204
205
claims = {"nbf" : "test" }
205
206
206
207
token = jwt .encode (claims , key )
207
208
208
209
with pytest .raises (JWTError ):
209
- jwt .decode (token , key )
210
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
210
211
211
212
def test_nbf_datetime (self , key ):
212
213
nbf = datetime .utcnow () - timedelta (seconds = 5 )
213
214
214
215
claims = {"nbf" : nbf }
215
216
216
217
token = jwt .encode (claims , key )
217
- jwt .decode (token , key )
218
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
218
219
219
220
def test_nbf_with_leeway (self , key ):
220
221
nbf = datetime .utcnow () + timedelta (seconds = 5 )
@@ -226,7 +227,7 @@ def test_nbf_with_leeway(self, key):
226
227
options = {"leeway" : 10 }
227
228
228
229
token = jwt .encode (claims , key )
229
- jwt .decode (token , key , options = options )
230
+ jwt .decode (token , key , options = options , algorithms = ALGORITHMS . HS256 )
230
231
231
232
def test_nbf_in_future (self , key ):
232
233
nbf = datetime .utcnow () + timedelta (seconds = 5 )
@@ -236,7 +237,7 @@ def test_nbf_in_future(self, key):
236
237
token = jwt .encode (claims , key )
237
238
238
239
with pytest .raises (JWTError ):
239
- jwt .decode (token , key )
240
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
240
241
241
242
def test_nbf_skip (self , key ):
242
243
nbf = datetime .utcnow () + timedelta (seconds = 5 )
@@ -246,27 +247,27 @@ def test_nbf_skip(self, key):
246
247
token = jwt .encode (claims , key )
247
248
248
249
with pytest .raises (JWTError ):
249
- jwt .decode (token , key )
250
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
250
251
251
252
options = {"verify_nbf" : False }
252
253
253
- jwt .decode (token , key , options = options )
254
+ jwt .decode (token , key , options = options , algorithms = ALGORITHMS . HS256 )
254
255
255
256
def test_exp_not_int (self , key ):
256
257
claims = {"exp" : "test" }
257
258
258
259
token = jwt .encode (claims , key )
259
260
260
261
with pytest .raises (JWTError ):
261
- jwt .decode (token , key )
262
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
262
263
263
264
def test_exp_datetime (self , key ):
264
265
exp = datetime .utcnow () + timedelta (seconds = 5 )
265
266
266
267
claims = {"exp" : exp }
267
268
268
269
token = jwt .encode (claims , key )
269
- jwt .decode (token , key )
270
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
270
271
271
272
def test_exp_with_leeway (self , key ):
272
273
exp = datetime .utcnow () - timedelta (seconds = 5 )
@@ -278,7 +279,7 @@ def test_exp_with_leeway(self, key):
278
279
options = {"leeway" : 10 }
279
280
280
281
token = jwt .encode (claims , key )
281
- jwt .decode (token , key , options = options )
282
+ jwt .decode (token , key , options = options , algorithms = ALGORITHMS . HS256 )
282
283
283
284
def test_exp_in_past (self , key ):
284
285
exp = datetime .utcnow () - timedelta (seconds = 5 )
@@ -288,7 +289,7 @@ def test_exp_in_past(self, key):
288
289
token = jwt .encode (claims , key )
289
290
290
291
with pytest .raises (JWTError ):
291
- jwt .decode (token , key )
292
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
292
293
293
294
def test_exp_skip (self , key ):
294
295
exp = datetime .utcnow () - timedelta (seconds = 5 )
@@ -298,35 +299,35 @@ def test_exp_skip(self, key):
298
299
token = jwt .encode (claims , key )
299
300
300
301
with pytest .raises (JWTError ):
301
- jwt .decode (token , key )
302
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
302
303
303
304
options = {"verify_exp" : False }
304
305
305
- jwt .decode (token , key , options = options )
306
+ jwt .decode (token , key , options = options , algorithms = ALGORITHMS . HS256 )
306
307
307
308
def test_aud_string (self , key ):
308
309
aud = "audience"
309
310
310
311
claims = {"aud" : aud }
311
312
312
313
token = jwt .encode (claims , key )
313
- jwt .decode (token , key , audience = aud )
314
+ jwt .decode (token , key , audience = aud , algorithms = ALGORITHMS . HS256 )
314
315
315
316
def test_aud_list (self , key ):
316
317
aud = "audience"
317
318
318
319
claims = {"aud" : [aud ]}
319
320
320
321
token = jwt .encode (claims , key )
321
- jwt .decode (token , key , audience = aud )
322
+ jwt .decode (token , key , audience = aud , algorithms = ALGORITHMS . HS256 )
322
323
323
324
def test_aud_list_multiple (self , key ):
324
325
aud = "audience"
325
326
326
327
claims = {"aud" : [aud , "another" ]}
327
328
328
329
token = jwt .encode (claims , key )
329
- jwt .decode (token , key , audience = aud )
330
+ jwt .decode (token , key , audience = aud , algorithms = ALGORITHMS . HS256 )
330
331
331
332
def test_aud_list_is_strings (self , key ):
332
333
aud = "audience"
@@ -335,7 +336,7 @@ def test_aud_list_is_strings(self, key):
335
336
336
337
token = jwt .encode (claims , key )
337
338
with pytest .raises (JWTError ):
338
- jwt .decode (token , key , audience = aud )
339
+ jwt .decode (token , key , audience = aud , algorithms = ALGORITHMS . HS256 )
339
340
340
341
def test_aud_case_sensitive (self , key ):
341
342
aud = "audience"
@@ -344,13 +345,13 @@ def test_aud_case_sensitive(self, key):
344
345
345
346
token = jwt .encode (claims , key )
346
347
with pytest .raises (JWTError ):
347
- jwt .decode (token , key , audience = "AUDIENCE" )
348
+ jwt .decode (token , key , audience = "AUDIENCE" , algorithms = ALGORITHMS . HS256 )
348
349
349
350
def test_aud_empty_claim (self , claims , key ):
350
351
aud = "audience"
351
352
352
353
token = jwt .encode (claims , key )
353
- jwt .decode (token , key , audience = aud )
354
+ jwt .decode (token , key , audience = aud , algorithms = ALGORITHMS . HS256 )
354
355
355
356
def test_aud_not_string_or_list (self , key ):
356
357
aud = 1
@@ -359,7 +360,7 @@ def test_aud_not_string_or_list(self, key):
359
360
360
361
token = jwt .encode (claims , key )
361
362
with pytest .raises (JWTError ):
362
- jwt .decode (token , key )
363
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
363
364
364
365
def test_aud_given_number (self , key ):
365
366
aud = "audience"
@@ -368,31 +369,31 @@ def test_aud_given_number(self, key):
368
369
369
370
token = jwt .encode (claims , key )
370
371
with pytest .raises (JWTError ):
371
- jwt .decode (token , key , audience = 1 )
372
+ jwt .decode (token , key , audience = 1 , algorithms = ALGORITHMS . HS256 )
372
373
373
374
def test_iss_string (self , key ):
374
375
iss = "issuer"
375
376
376
377
claims = {"iss" : iss }
377
378
378
379
token = jwt .encode (claims , key )
379
- jwt .decode (token , key , issuer = iss )
380
+ jwt .decode (token , key , issuer = iss , algorithms = ALGORITHMS . HS256 )
380
381
381
382
def test_iss_list (self , key ):
382
383
iss = "issuer"
383
384
384
385
claims = {"iss" : iss }
385
386
386
387
token = jwt .encode (claims , key )
387
- jwt .decode (token , key , issuer = ["https://issuer" , "issuer" ])
388
+ jwt .decode (token , key , issuer = ["https://issuer" , "issuer" ], algorithms = ALGORITHMS . HS256 )
388
389
389
390
def test_iss_tuple (self , key ):
390
391
iss = "issuer"
391
392
392
393
claims = {"iss" : iss }
393
394
394
395
token = jwt .encode (claims , key )
395
- jwt .decode (token , key , issuer = ("https://issuer" , "issuer" ))
396
+ jwt .decode (token , key , issuer = ("https://issuer" , "issuer" ), algorithms = ALGORITHMS . HS256 )
396
397
397
398
def test_iss_invalid (self , key ):
398
399
iss = "issuer"
@@ -401,15 +402,15 @@ def test_iss_invalid(self, key):
401
402
402
403
token = jwt .encode (claims , key )
403
404
with pytest .raises (JWTError ):
404
- jwt .decode (token , key , issuer = "another" )
405
+ jwt .decode (token , key , issuer = "another" , algorithms = ALGORITHMS . HS256 )
405
406
406
407
def test_sub_string (self , key ):
407
408
sub = "subject"
408
409
409
410
claims = {"sub" : sub }
410
411
411
412
token = jwt .encode (claims , key )
412
- jwt .decode (token , key )
413
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
413
414
414
415
def test_sub_invalid (self , key ):
415
416
sub = 1
@@ -418,15 +419,15 @@ def test_sub_invalid(self, key):
418
419
419
420
token = jwt .encode (claims , key )
420
421
with pytest .raises (JWTError ):
421
- jwt .decode (token , key )
422
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
422
423
423
424
def test_sub_correct (self , key ):
424
425
sub = "subject"
425
426
426
427
claims = {"sub" : sub }
427
428
428
429
token = jwt .encode (claims , key )
429
- jwt .decode (token , key , subject = sub )
430
+ jwt .decode (token , key , subject = sub , algorithms = ALGORITHMS . HS256 )
430
431
431
432
def test_sub_incorrect (self , key ):
432
433
sub = "subject"
@@ -435,15 +436,15 @@ def test_sub_incorrect(self, key):
435
436
436
437
token = jwt .encode (claims , key )
437
438
with pytest .raises (JWTError ):
438
- jwt .decode (token , key , subject = "another" )
439
+ jwt .decode (token , key , subject = "another" , algorithms = ALGORITHMS . HS256 )
439
440
440
441
def test_jti_string (self , key ):
441
442
jti = "JWT ID"
442
443
443
444
claims = {"jti" : jti }
444
445
445
446
token = jwt .encode (claims , key )
446
- jwt .decode (token , key )
447
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
447
448
448
449
def test_jti_invalid (self , key ):
449
450
jti = 1
@@ -452,33 +453,33 @@ def test_jti_invalid(self, key):
452
453
453
454
token = jwt .encode (claims , key )
454
455
with pytest .raises (JWTError ):
455
- jwt .decode (token , key )
456
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
456
457
457
458
def test_at_hash (self , claims , key ):
458
459
access_token = "<ACCESS_TOKEN>"
459
460
token = jwt .encode (claims , key , access_token = access_token )
460
- payload = jwt .decode (token , key , access_token = access_token )
461
+ payload = jwt .decode (token , key , access_token = access_token , algorithms = ALGORITHMS . HS256 )
461
462
assert "at_hash" in payload
462
463
463
464
def test_at_hash_invalid (self , claims , key ):
464
465
token = jwt .encode (claims , key , access_token = "<ACCESS_TOKEN>" )
465
466
with pytest .raises (JWTError ):
466
- jwt .decode (token , key , access_token = "<OTHER_TOKEN>" )
467
+ jwt .decode (token , key , access_token = "<OTHER_TOKEN>" , algorithms = ALGORITHMS . HS256 )
467
468
468
469
def test_at_hash_missing_access_token (self , claims , key ):
469
470
token = jwt .encode (claims , key , access_token = "<ACCESS_TOKEN>" )
470
471
with pytest .raises (JWTError ):
471
- jwt .decode (token , key )
472
+ jwt .decode (token , key , algorithms = ALGORITHMS . HS256 )
472
473
473
474
def test_at_hash_missing_claim (self , claims , key ):
474
475
token = jwt .encode (claims , key )
475
- payload = jwt .decode (token , key , access_token = "<ACCESS_TOKEN>" )
476
+ payload = jwt .decode (token , key , access_token = "<ACCESS_TOKEN>" , algorithms = ALGORITHMS . HS256 )
476
477
assert "at_hash" not in payload
477
478
478
479
def test_at_hash_unable_to_calculate (self , claims , key ):
479
480
token = jwt .encode (claims , key , access_token = "<ACCESS_TOKEN>" )
480
481
with pytest .raises (JWTError ):
481
- jwt .decode (token , key , access_token = "\xe2 " )
482
+ jwt .decode (token , key , access_token = "\xe2 " , algorithms = ALGORITHMS . HS256 )
482
483
483
484
def test_bad_claims (self ):
484
485
bad_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.iOJ5SiNfaNO_pa2J4Umtb3b3zmk5C18-mhTCVNsjnck"
@@ -516,12 +517,12 @@ def test_require(self, claims, key, claim, value):
516
517
517
518
token = jwt .encode (claims , key )
518
519
with pytest .raises (JWTError ):
519
- jwt .decode (token , key , options = options , audience = str (value ))
520
+ jwt .decode (token , key , options = options , audience = str (value ), algorithms = ALGORITHMS . HS256 )
520
521
521
522
new_claims = dict (claims )
522
523
new_claims [claim ] = value
523
524
token = jwt .encode (new_claims , key )
524
- jwt .decode (token , key , options = options , audience = str (value ))
525
+ jwt .decode (token , key , options = options , audience = str (value ), algorithms = ALGORITHMS . HS256 )
525
526
526
527
def test_CVE_2024_33663 (self ):
527
528
"""Test based on https://github.com/mpdavis/python-jose/issues/346"""
@@ -554,4 +555,7 @@ def test_CVE_2024_33663(self):
554
555
# algorithm field is left unspecified
555
556
# but the library will happily still verify without warning, trusting the user-controlled alg field of the token header
556
557
with pytest .raises (JWKError ):
558
+ data = jwt .decode (evil_token , PUBKEY , algorithms = ALGORITHMS .HS256 )
559
+
560
+ with pytest .raises (JWTError , match = '.*required.*"algorithms".*' ):
557
561
data = jwt .decode (evil_token , PUBKEY )
0 commit comments