Skip to content

Commit ae1ea58

Browse files
Support jwt 2 (jazzband#376)
* Add PyJWT 2.0.0 support * Many tests relied on passing a payload into encode and changing it payload by reference. In PyJWT 2.0.0, the payload is copied (`dict.copy()`). * Verify was deprecated in favor of using the option verify_signature. This is reflected in backends.py. Unless you wrote verify=False, you are not effected by this change. * Isort lint Co-authored-by: Andrew-Chen-Wang <acwangpython@gmail.com>
1 parent c684e83 commit ae1ea58

File tree

2 files changed

+33
-19
lines changed

2 files changed

+33
-19
lines changed

rest_framework_simplejwt/backends.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@ def decode(self, token, verify=True):
6565
signature check fails, or if its 'exp' claim indicates it has expired.
6666
"""
6767
try:
68-
return jwt.decode(token, self.verifying_key, algorithms=[self.algorithm], verify=verify,
69-
audience=self.audience, issuer=self.issuer,
70-
options={'verify_aud': self.audience is not None})
68+
return jwt.decode(
69+
token, self.verifying_key, algorithms=[self.algorithm], verify=verify,
70+
audience=self.audience, issuer=self.issuer,
71+
options={'verify_aud': self.audience is not None, "verify_signature": verify}
72+
)
7173
except InvalidAlgorithmError as ex:
7274
raise TokenBackendError(_('Invalid algorithm specified')) from ex
7375
except InvalidTokenError:

tests/test_backends.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33

44
import jwt
55
from django.test import TestCase
6-
from jwt import PyJWT, algorithms
6+
from jwt import PyJWS, algorithms
77

88
from rest_framework_simplejwt.backends import TokenBackend
99
from rest_framework_simplejwt.exceptions import TokenBackendError
10-
from rest_framework_simplejwt.utils import aware_utcnow, make_utc
10+
from rest_framework_simplejwt.utils import (
11+
aware_utcnow, datetime_to_epoch, make_utc,
12+
)
1113

1214
SECRET = 'not_secret'
1315

@@ -163,9 +165,9 @@ def test_decode_hmac_with_expiry(self):
163165

164166
def test_decode_hmac_with_invalid_sig(self):
165167
self.payload['exp'] = aware_utcnow() + timedelta(days=1)
166-
token_1 = jwt.encode(self.payload, SECRET, algorithm='HS256').decode('utf-8')
168+
token_1 = jwt.encode(self.payload, SECRET, algorithm='HS256')
167169
self.payload['foo'] = 'baz'
168-
token_2 = jwt.encode(self.payload, SECRET, algorithm='HS256').decode('utf-8')
170+
token_2 = jwt.encode(self.payload, SECRET, algorithm='HS256')
169171

170172
token_2_payload = token_2.rsplit('.', 1)[0]
171173
token_1_sig = token_1.rsplit('.', 1)[-1]
@@ -176,9 +178,11 @@ def test_decode_hmac_with_invalid_sig(self):
176178

177179
def test_decode_hmac_with_invalid_sig_no_verify(self):
178180
self.payload['exp'] = aware_utcnow() + timedelta(days=1)
179-
token_1 = jwt.encode(self.payload, SECRET, algorithm='HS256').decode('utf-8')
181+
token_1 = jwt.encode(self.payload, SECRET, algorithm='HS256')
180182
self.payload['foo'] = 'baz'
181-
token_2 = jwt.encode(self.payload, SECRET, algorithm='HS256').decode('utf-8')
183+
token_2 = jwt.encode(self.payload, SECRET, algorithm='HS256')
184+
# Payload copied
185+
self.payload["exp"] = datetime_to_epoch(self.payload["exp"])
182186

183187
token_2_payload = token_2.rsplit('.', 1)[0]
184188
token_1_sig = token_1.rsplit('.', 1)[-1]
@@ -193,7 +197,9 @@ def test_decode_hmac_success(self):
193197
self.payload['exp'] = aware_utcnow() + timedelta(days=1)
194198
self.payload['foo'] = 'baz'
195199

196-
token = jwt.encode(self.payload, SECRET, algorithm='HS256').decode('utf-8')
200+
token = jwt.encode(self.payload, SECRET, algorithm='HS256')
201+
# Payload copied
202+
self.payload["exp"] = datetime_to_epoch(self.payload["exp"])
197203

198204
self.assertEqual(self.hmac_token_backend.decode(token), self.payload)
199205

@@ -220,9 +226,9 @@ def test_decode_rsa_with_expiry(self):
220226

221227
def test_decode_rsa_with_invalid_sig(self):
222228
self.payload['exp'] = aware_utcnow() + timedelta(days=1)
223-
token_1 = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256').decode('utf-8')
229+
token_1 = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256')
224230
self.payload['foo'] = 'baz'
225-
token_2 = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256').decode('utf-8')
231+
token_2 = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256')
226232

227233
token_2_payload = token_2.rsplit('.', 1)[0]
228234
token_1_sig = token_1.rsplit('.', 1)[-1]
@@ -233,13 +239,15 @@ def test_decode_rsa_with_invalid_sig(self):
233239

234240
def test_decode_rsa_with_invalid_sig_no_verify(self):
235241
self.payload['exp'] = aware_utcnow() + timedelta(days=1)
236-
token_1 = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256').decode('utf-8')
242+
token_1 = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256')
237243
self.payload['foo'] = 'baz'
238-
token_2 = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256').decode('utf-8')
244+
token_2 = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256')
239245

240246
token_2_payload = token_2.rsplit('.', 1)[0]
241247
token_1_sig = token_1.rsplit('.', 1)[-1]
242248
invalid_token = token_2_payload + '.' + token_1_sig
249+
# Payload copied
250+
self.payload["exp"] = datetime_to_epoch(self.payload["exp"])
243251

244252
self.assertEqual(
245253
self.hmac_token_backend.decode(invalid_token, verify=False),
@@ -250,7 +258,9 @@ def test_decode_rsa_success(self):
250258
self.payload['exp'] = aware_utcnow() + timedelta(days=1)
251259
self.payload['foo'] = 'baz'
252260

253-
token = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256').decode('utf-8')
261+
token = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256')
262+
# Payload copied
263+
self.payload["exp"] = datetime_to_epoch(self.payload["exp"])
254264

255265
self.assertEqual(self.rsa_token_backend.decode(token), self.payload)
256266

@@ -260,21 +270,23 @@ def test_decode_aud_iss_success(self):
260270
self.payload['aud'] = AUDIENCE
261271
self.payload['iss'] = ISSUER
262272

263-
token = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256').decode('utf-8')
273+
token = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256')
274+
# Payload copied
275+
self.payload["exp"] = datetime_to_epoch(self.payload["exp"])
264276

265277
self.assertEqual(self.aud_iss_token_backend.decode(token), self.payload)
266278

267279
def test_decode_when_algorithm_not_available(self):
268-
token = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256').decode('utf-8')
280+
token = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256')
269281

270-
pyjwt_without_rsa = PyJWT()
282+
pyjwt_without_rsa = PyJWS()
271283
pyjwt_without_rsa.unregister_algorithm('RS256')
272284
with patch.object(jwt, 'decode', new=pyjwt_without_rsa.decode):
273285
with self.assertRaisesRegex(TokenBackendError, 'Invalid algorithm specified'):
274286
self.rsa_token_backend.decode(token)
275287

276288
def test_decode_when_token_algorithm_does_not_match(self):
277-
token = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256').decode('utf-8')
289+
token = jwt.encode(self.payload, PRIVATE_KEY, algorithm='RS256')
278290

279291
with self.assertRaisesRegex(TokenBackendError, 'Invalid algorithm specified'):
280292
self.hmac_token_backend.decode(token)

0 commit comments

Comments
 (0)