class TestAPI(unittest.TestCase): def setUp(self): # noqa self.payload = {'iss': 'jeff', 'exp': utc_timestamp() + 15, 'claim': 'insanity'} self.jwt = PyJWT() def test_register_algorithm_does_not_allow_duplicate_registration(self): self.jwt.register_algorithm('AAA', Algorithm()) with self.assertRaises(ValueError): self.jwt.register_algorithm('AAA', Algorithm()) def test_register_algorithm_rejects_non_algorithm_obj(self): with self.assertRaises(TypeError): self.jwt.register_algorithm('AAA123', {}) def test_unregister_algorithm_removes_algorithm(self): supported = self.jwt.get_algorithms() self.assertIn('none', supported) self.assertIn('HS256', supported) self.jwt.unregister_algorithm('HS256') supported = self.jwt.get_algorithms() self.assertNotIn('HS256', supported) def test_unregister_algorithm_throws_error_if_not_registered(self): with self.assertRaises(KeyError): self.jwt.unregister_algorithm('AAA') def test_algorithms_parameter_removes_alg_from_algorithms_list(self): self.assertIn('none', self.jwt.get_algorithms()) self.assertIn('HS256', self.jwt.get_algorithms()) self.jwt = PyJWT(algorithms=['HS256']) self.assertNotIn('none', self.jwt.get_algorithms()) self.assertIn('HS256', self.jwt.get_algorithms()) def test_encode_decode(self): secret = 'secret' jwt_message = self.jwt.encode(self.payload, secret) decoded_payload = self.jwt.decode(jwt_message, secret) self.assertEqual(decoded_payload, self.payload) def test_decode_fails_when_alg_is_not_on_method_algorithms_param(self): secret = 'secret' jwt_token = self.jwt.encode(self.payload, secret, algorithm='HS256') self.jwt.decode(jwt_token, secret) with self.assertRaises(InvalidAlgorithmError): self.jwt.decode(jwt_token, secret, algorithms=['HS384']) def test_decode_works_with_unicode_token(self): secret = 'secret' unicode_jwt = text_type( 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9' '.eyJoZWxsbyI6ICJ3b3JsZCJ9' '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') self.jwt.decode(unicode_jwt, secret) def test_decode_missing_segments_throws_exception(self): secret = 'secret' example_jwt = ('eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9' '.eyJoZWxsbyI6ICJ3b3JsZCJ9' '') # Missing segment with self.assertRaises(DecodeError) as context: self.jwt.decode(example_jwt, secret) exception = context.exception self.assertEqual(str(exception), 'Not enough segments') def test_decode_with_non_mapping_header_throws_exception(self): secret = 'secret' example_jwt = ('MQ' # == 1 '.eyJoZWxsbyI6ICJ3b3JsZCJ9' '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') with self.assertRaises(DecodeError) as context: self.jwt.decode(example_jwt, secret) exception = context.exception self.assertEqual(str(exception), 'Invalid header string: must be a json object') def test_decode_with_non_mapping_payload_throws_exception(self): secret = 'secret' example_jwt = ('eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9' '.MQ' # == 1 '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') with self.assertRaises(DecodeError) as context: self.jwt.decode(example_jwt, secret) exception = context.exception self.assertEqual(str(exception), 'Invalid payload string: must be a json object') def test_decode_with_invalid_audience_param_throws_exception(self): secret = 'secret' example_jwt = ('eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9' '.eyJoZWxsbyI6ICJ3b3JsZCJ9' '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') with self.assertRaises(TypeError) as context: self.jwt.decode(example_jwt, secret, audience=1) exception = context.exception self.assertEqual(str(exception), 'audience must be a string or None') def test_decode_with_nonlist_aud_claim_throws_exception(self): secret = 'secret' example_jwt = ('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9' '.eyJoZWxsbyI6IndvcmxkIiwiYXVkIjoxfQ' # aud = 1 '.Rof08LBSwbm8Z_bhA2N3DFY-utZR1Gi9rbIS5Zthnnc') with self.assertRaises(InvalidAudienceError) as context: self.jwt.decode(example_jwt, secret, audience='my_audience') exception = context.exception self.assertEqual(str(exception), 'Invalid claim format in token') def test_decode_with_invalid_aud_list_member_throws_exception(self): secret = 'secret' example_jwt = ('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9' '.eyJoZWxsbyI6IndvcmxkIiwiYXVkIjpbMV19' '.iQgKpJ8shetwNMIosNXWBPFB057c2BHs-8t1d2CCM2A') with self.assertRaises(InvalidAudienceError) as context: self.jwt.decode(example_jwt, secret, audience='my_audience') exception = context.exception self.assertEqual(str(exception), 'Invalid claim format in token') def test_encode_bad_type(self): types = ['string', tuple(), list(), 42, set()] for t in types: self.assertRaises(TypeError, lambda: self.jwt.encode(t, 'secret')) def test_encode_algorithm_param_should_be_case_sensitive(self): payload = {'hello': 'world'} self.jwt.encode(payload, 'secret', algorithm='HS256') with self.assertRaises(NotImplementedError) as context: self.jwt.encode(payload, None, algorithm='hs256') exception = context.exception self.assertEquals(str(exception), 'Algorithm not supported') def test_decode_algorithm_param_should_be_case_sensitive(self): example_jwt = ('eyJhbGciOiJoczI1NiIsInR5cCI6IkpXVCJ9' # alg = hs256 '.eyJoZWxsbyI6IndvcmxkIn0' '.5R_FEPE7SW2dT9GgIxPgZATjFGXfUDOSwo7TtO_Kd_g') with self.assertRaises(InvalidAlgorithmError) as context: self.jwt.decode(example_jwt, 'secret') exception = context.exception self.assertEquals(str(exception), 'Algorithm not supported') def test_decode_raises_exception_if_exp_is_not_int(self): # >>> jwt.encode({'exp': 'not-an-int'}, 'secret') example_jwt = ('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.' 'eyJleHAiOiJub3QtYW4taW50In0.' 'P65iYgoHtBqB07PMtBSuKNUEIPPPfmjfJG217cEE66s') with self.assertRaisesRegexp(DecodeError, 'exp'): self.jwt.decode(example_jwt, 'secret') def test_decode_raises_exception_if_iat_is_not_int(self): # >>> jwt.encode({'iat': 'not-an-int'}, 'secret') example_jwt = ('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.' 'eyJpYXQiOiJub3QtYW4taW50In0.' 'H1GmcQgSySa5LOKYbzGm--b1OmRbHFkyk8pq811FzZM') with self.assertRaises(DecodeError): self.jwt.decode(example_jwt, 'secret') def test_decode_raises_exception_if_nbf_is_not_int(self): # >>> jwt.encode({'nbf': 'not-an-int'}, 'secret') example_jwt = ('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.' 'eyJuYmYiOiJub3QtYW4taW50In0.' 'c25hldC8G2ZamC8uKpax9sYMTgdZo3cxrmzFHaAAluw') with self.assertRaises(DecodeError): self.jwt.decode(example_jwt, 'secret') def test_decode_raises_exception_if_iat_in_the_future(self): now = datetime.utcnow() token = self.jwt.encode({'iat': now + timedelta(days=1)}, key='secret') with self.assertRaises(InvalidIssuedAtError): self.jwt.decode(token, 'secret') def test_encode_datetime(self): secret = 'secret' current_datetime = datetime.utcnow() payload = { 'exp': current_datetime, 'iat': current_datetime, 'nbf': current_datetime } jwt_message = self.jwt.encode(payload, secret) decoded_payload = self.jwt.decode(jwt_message, secret, leeway=1) self.assertEqual( decoded_payload['exp'], timegm(current_datetime.utctimetuple())) self.assertEqual( decoded_payload['iat'], timegm(current_datetime.utctimetuple())) self.assertEqual( decoded_payload['nbf'], timegm(current_datetime.utctimetuple())) def test_bad_secret(self): right_secret = 'foo' bad_secret = 'bar' jwt_message = self.jwt.encode(self.payload, right_secret) self.assertRaises( DecodeError, lambda: self.jwt.decode(jwt_message, bad_secret)) def test_decodes_valid_jwt(self): example_payload = {'hello': 'world'} example_secret = 'secret' example_jwt = ( b'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9' b'.eyJoZWxsbyI6ICJ3b3JsZCJ9' b'.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') decoded_payload = self.jwt.decode(example_jwt, example_secret) self.assertEqual(decoded_payload, example_payload) # 'Control' Elliptic Curve JWT created by another library. # Used to test for regressions that could affect both # encoding / decoding operations equally (causing tests # to still pass). @unittest.skipIf(not has_crypto, "Can't run without cryptography library") def test_decodes_valid_es384_jwt(self): example_payload = {'hello': 'world'} with open('tests/keys/testkey_ec.pub', 'r') as fp: example_pubkey = fp.read() example_jwt = ( b'eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9' b'.eyJoZWxsbyI6IndvcmxkIn0' b'.MIGHAkEdh2kR7IRu5w0tGuY6Xz3Vqa7PHHY2DgXWeee' b'LXotEqpn9udp2NfVL-XFG0TDoCakzXbIGAWg42S69GFl' b'KZzxhXAJCAPLPuJoKyAixFnXPBkvkti-UzSIj4s6DePe' b'uTu7102G_QIXiijY5bx6mdmZa3xUuKeu-zobOIOqR8Zw' b'FqGjBLZum') decoded_payload = self.jwt.decode(example_jwt, example_pubkey) self.assertEqual(decoded_payload, example_payload) # 'Control' RSA JWT created by another library. # Used to test for regressions that could affect both # encoding / decoding operations equally (causing tests # to still pass). @unittest.skipIf(not has_crypto, "Can't run without cryptography library") def test_decodes_valid_rs384_jwt(self): example_payload = {'hello': 'world'} with open('tests/keys/testkey_rsa.pub', 'r') as fp: example_pubkey = fp.read() example_jwt = ( b'eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9' b'.eyJoZWxsbyI6IndvcmxkIn0' b'.yNQ3nI9vEDs7lEh-Cp81McPuiQ4ZRv6FL4evTYYAh1X' b'lRTTR3Cz8pPA9Stgso8Ra9xGB4X3rlra1c8Jz10nTUju' b'O06OMm7oXdrnxp1KIiAJDerWHkQ7l3dlizIk1bmMA457' b'W2fNzNfHViuED5ISM081dgf_a71qBwJ_yShMMrSOfxDx' b'mX9c4DjRogRJG8SM5PvpLqI_Cm9iQPGMvmYK7gzcq2cJ' b'urHRJDJHTqIdpLWXkY7zVikeen6FhuGyn060Dz9gYq9t' b'uwmrtSWCBUjiN8sqJ00CDgycxKqHfUndZbEAOjcCAhBr' b'qWW3mSVivUfubsYbwUdUG3fSRPjaUPcpe8A') decoded_payload = self.jwt.decode(example_jwt, example_pubkey) self.assertEqual(decoded_payload, example_payload) def test_load_verify_valid_jwt(self): example_payload = {'hello': 'world'} example_secret = 'secret' example_jwt = ( b'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9' b'.eyJoZWxsbyI6ICJ3b3JsZCJ9' b'.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') decoded_payload = self.jwt.decode(example_jwt, key=example_secret) self.assertEqual(decoded_payload, example_payload) def test_allow_skip_verification(self): right_secret = 'foo' jwt_message = self.jwt.encode(self.payload, right_secret) decoded_payload = self.jwt.decode(jwt_message, verify=False) self.assertEqual(decoded_payload, self.payload) def test_load_no_verification(self): right_secret = 'foo' jwt_message = self.jwt.encode(self.payload, right_secret) decoded_payload = self.jwt.decode(jwt_message, key=None, verify=False) self.assertEqual(decoded_payload, self.payload) def test_no_secret(self): right_secret = 'foo' jwt_message = self.jwt.encode(self.payload, right_secret) self.assertRaises( DecodeError, lambda: self.jwt.decode(jwt_message)) def test_verify_signature_with_no_secret(self): right_secret = 'foo' jwt_message = self.jwt.encode(self.payload, right_secret) with self.assertRaisesRegexp(DecodeError, 'Signature verification'): self.jwt.decode(jwt_message) def test_invalid_crypto_alg(self): with self.assertRaises(NotImplementedError): self.jwt.encode(self.payload, 'secret', algorithm='HS1024') def test_unicode_secret(self): secret = '\xc2' jwt_message = self.jwt.encode(self.payload, secret) decoded_payload = self.jwt.decode(jwt_message, secret) self.assertEqual(decoded_payload, self.payload) def test_nonascii_secret(self): secret = '\xc2' # char value that ascii codec cannot decode jwt_message = self.jwt.encode(self.payload, secret) decoded_payload = self.jwt.decode(jwt_message, secret) self.assertEqual(decoded_payload, self.payload) def test_bytes_secret(self): secret = b'\xc2' # char value that ascii codec cannot decode jwt_message = self.jwt.encode(self.payload, secret) decoded_payload = self.jwt.decode(jwt_message, secret) self.assertEqual(decoded_payload, self.payload) def test_decode_unicode_value(self): example_payload = {'hello': 'world'} example_secret = 'secret' example_jwt = ( 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9' '.eyJoZWxsbyI6ICJ3b3JsZCJ9' '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') decoded_payload = self.jwt.decode(example_jwt, example_secret) self.assertEqual(decoded_payload, example_payload) def test_decode_invalid_header_padding(self): example_jwt = ( 'aeyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9' '.eyJoZWxsbyI6ICJ3b3JsZCJ9' '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') example_secret = 'secret' with self.assertRaisesRegexp(DecodeError, 'header padding'): self.jwt.decode(example_jwt, example_secret) def test_decode_invalid_header_string(self): example_jwt = ( 'eyJhbGciOiAiSFMyNTbpIiwgInR5cCI6ICJKV1QifQ==' '.eyJoZWxsbyI6ICJ3b3JsZCJ9' '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') example_secret = 'secret' with self.assertRaisesRegexp(DecodeError, 'Invalid header'): self.jwt.decode(example_jwt, example_secret) def test_decode_invalid_payload_padding(self): example_jwt = ( 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9' '.aeyJoZWxsbyI6ICJ3b3JsZCJ9' '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') example_secret = 'secret' with self.assertRaisesRegexp(DecodeError, 'Invalid payload padding'): self.jwt.decode(example_jwt, example_secret) def test_decode_invalid_payload_string(self): example_jwt = ( 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9' '.eyJoZWxsb-kiOiAid29ybGQifQ==' '.tvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') example_secret = 'secret' with self.assertRaisesRegexp(DecodeError, 'Invalid payload string'): self.jwt.decode(example_jwt, example_secret) def test_decode_invalid_crypto_padding(self): example_jwt = ( 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9' '.eyJoZWxsbyI6ICJ3b3JsZCJ9' '.aatvagLDLoaiJKxOKqpBXSEGy7SYSifZhjntgm9ctpyj8') example_secret = 'secret' with self.assertRaisesRegexp(DecodeError, 'Invalid crypto padding'): self.jwt.decode(example_jwt, example_secret) def test_decode_with_expiration(self): self.payload['exp'] = utc_timestamp() - 1 secret = 'secret' jwt_message = self.jwt.encode(self.payload, secret) with self.assertRaises(ExpiredSignatureError): self.jwt.decode(jwt_message, secret) def test_decode_with_notbefore(self): self.payload['nbf'] = utc_timestamp() + 10 secret = 'secret' jwt_message = self.jwt.encode(self.payload, secret) with self.assertRaises(ImmatureSignatureError): self.jwt.decode(jwt_message, secret) def test_decode_skip_expiration_verification(self): self.payload['exp'] = time.time() - 1 secret = 'secret' jwt_message = self.jwt.encode(self.payload, secret) self.jwt.decode(jwt_message, secret, verify_expiration=False) def test_decode_skip_notbefore_verification(self): self.payload['nbf'] = time.time() + 10 secret = 'secret' jwt_message = self.jwt.encode(self.payload, secret) self.jwt.decode(jwt_message, secret, verify_expiration=False) def test_decode_with_expiration_with_leeway(self): self.payload['exp'] = utc_timestamp() - 2 secret = 'secret' jwt_message = self.jwt.encode(self.payload, secret) decoded_payload, signing, header, signature = self.jwt._load(jwt_message) # With 3 seconds leeway, should be ok for leeway in (3, timedelta(seconds=3)): self.jwt.decode(jwt_message, secret, leeway=leeway) # With 1 seconds, should fail for leeway in (1, timedelta(seconds=1)): with self.assertRaises(ExpiredSignatureError): self.jwt.decode(jwt_message, secret, leeway=leeway) def test_decode_with_notbefore_with_leeway(self): self.payload['nbf'] = utc_timestamp() + 10 secret = 'secret' jwt_message = self.jwt.encode(self.payload, secret) # With 13 seconds leeway, should be ok self.jwt.decode(jwt_message, secret, leeway=13) with self.assertRaises(ImmatureSignatureError): self.jwt.decode(jwt_message, secret, leeway=1) def test_decode_with_algo_none_should_fail(self): jwt_message = self.jwt.encode(self.payload, key=None, algorithm=None) with self.assertRaises(DecodeError): self.jwt.decode(jwt_message) def test_decode_with_algo_none_and_verify_false_should_pass(self): jwt_message = self.jwt.encode(self.payload, key=None, algorithm=None) self.jwt.decode(jwt_message, verify=False) @unittest.skipIf(not has_crypto, 'Not supported without cryptography library') def test_encode_decode_with_rsa_sha256(self): # PEM-formatted RSA key with open('tests/keys/testkey_rsa', 'r') as rsa_priv_file: priv_rsakey = load_pem_private_key(ensure_bytes(rsa_priv_file.read()), password=None, backend=default_backend()) jwt_message = self.jwt.encode(self.payload, priv_rsakey, algorithm='RS256') with open('tests/keys/testkey_rsa.pub', 'r') as rsa_pub_file: pub_rsakey = load_ssh_public_key(ensure_bytes(rsa_pub_file.read()), backend=default_backend()) self.jwt.decode(jwt_message, pub_rsakey) # string-formatted key with open('tests/keys/testkey_rsa', 'r') as rsa_priv_file: priv_rsakey = rsa_priv_file.read() jwt_message = self.jwt.encode(self.payload, priv_rsakey, algorithm='RS256') with open('tests/keys/testkey_rsa.pub', 'r') as rsa_pub_file: pub_rsakey = rsa_pub_file.read() self.jwt.decode(jwt_message, pub_rsakey) @unittest.skipIf(not has_crypto, 'Not supported without cryptography library') def test_encode_decode_with_rsa_sha384(self): # PEM-formatted RSA key with open('tests/keys/testkey_rsa', 'r') as rsa_priv_file: priv_rsakey = load_pem_private_key(ensure_bytes(rsa_priv_file.read()), password=None, backend=default_backend()) jwt_message = self.jwt.encode(self.payload, priv_rsakey, algorithm='RS384') with open('tests/keys/testkey_rsa.pub', 'r') as rsa_pub_file: pub_rsakey = load_ssh_public_key(ensure_bytes(rsa_pub_file.read()), backend=default_backend()) assert self.jwt.decode(jwt_message, pub_rsakey) # string-formatted key with open('tests/keys/testkey_rsa', 'r') as rsa_priv_file: priv_rsakey = rsa_priv_file.read() jwt_message = self.jwt.encode(self.payload, priv_rsakey, algorithm='RS384') with open('tests/keys/testkey_rsa.pub', 'r') as rsa_pub_file: pub_rsakey = rsa_pub_file.read() self.jwt.decode(jwt_message, pub_rsakey) @unittest.skipIf(not has_crypto, 'Not supported without cryptography library') def test_encode_decode_with_rsa_sha512(self): # PEM-formatted RSA key with open('tests/keys/testkey_rsa', 'r') as rsa_priv_file: priv_rsakey = load_pem_private_key(ensure_bytes(rsa_priv_file.read()), password=None, backend=default_backend()) jwt_message = self.jwt.encode(self.payload, priv_rsakey, algorithm='RS512') with open('tests/keys/testkey_rsa.pub', 'r') as rsa_pub_file: pub_rsakey = load_ssh_public_key(ensure_bytes(rsa_pub_file.read()), backend=default_backend()) self.jwt.decode(jwt_message, pub_rsakey) # string-formatted key with open('tests/keys/testkey_rsa', 'r') as rsa_priv_file: priv_rsakey = rsa_priv_file.read() jwt_message = self.jwt.encode(self.payload, priv_rsakey, algorithm='RS512') with open('tests/keys/testkey_rsa.pub', 'r') as rsa_pub_file: pub_rsakey = rsa_pub_file.read() self.jwt.decode(jwt_message, pub_rsakey) def test_rsa_related_algorithms(self): self.jwt = PyJWT() jwt_algorithms = self.jwt.get_algorithms() if has_crypto: self.assertTrue('RS256' in jwt_algorithms) self.assertTrue('RS384' in jwt_algorithms) self.assertTrue('RS512' in jwt_algorithms) else: self.assertFalse('RS256' in jwt_algorithms) self.assertFalse('RS384' in jwt_algorithms) self.assertFalse('RS512' in jwt_algorithms) @unittest.skipIf(not has_crypto, "Can't run without cryptography library") def test_encode_decode_with_ecdsa_sha256(self): # PEM-formatted EC key with open('tests/keys/testkey_ec', 'r') as ec_priv_file: priv_eckey = load_pem_private_key(ensure_bytes(ec_priv_file.read()), password=None, backend=default_backend()) jwt_message = self.jwt.encode(self.payload, priv_eckey, algorithm='ES256') with open('tests/keys/testkey_ec.pub', 'r') as ec_pub_file: pub_eckey = load_pem_public_key(ensure_bytes(ec_pub_file.read()), backend=default_backend()) self.jwt.decode(jwt_message, pub_eckey) # string-formatted key with open('tests/keys/testkey_ec', 'r') as ec_priv_file: priv_eckey = ec_priv_file.read() jwt_message = self.jwt.encode(self.payload, priv_eckey, algorithm='ES256') with open('tests/keys/testkey_ec.pub', 'r') as ec_pub_file: pub_eckey = ec_pub_file.read() self.jwt.decode(jwt_message, pub_eckey) @unittest.skipIf(not has_crypto, "Can't run without cryptography library") def test_encode_decode_with_ecdsa_sha384(self): # PEM-formatted EC key with open('tests/keys/testkey_ec', 'r') as ec_priv_file: priv_eckey = load_pem_private_key(ensure_bytes(ec_priv_file.read()), password=None, backend=default_backend()) jwt_message = self.jwt.encode(self.payload, priv_eckey, algorithm='ES384') with open('tests/keys/testkey_ec.pub', 'r') as ec_pub_file: pub_eckey = load_pem_public_key(ensure_bytes(ec_pub_file.read()), backend=default_backend()) self.jwt.decode(jwt_message, pub_eckey) # string-formatted key with open('tests/keys/testkey_ec', 'r') as ec_priv_file: priv_eckey = ec_priv_file.read() jwt_message = self.jwt.encode(self.payload, priv_eckey, algorithm='ES384') with open('tests/keys/testkey_ec.pub', 'r') as ec_pub_file: pub_eckey = ec_pub_file.read() self.jwt.decode(jwt_message, pub_eckey) @unittest.skipIf(not has_crypto, "Can't run without cryptography library") def test_encode_decode_with_ecdsa_sha512(self): # PEM-formatted EC key with open('tests/keys/testkey_ec', 'r') as ec_priv_file: priv_eckey = load_pem_private_key(ensure_bytes(ec_priv_file.read()), password=None, backend=default_backend()) jwt_message = self.jwt.encode(self.payload, priv_eckey, algorithm='ES512') with open('tests/keys/testkey_ec.pub', 'r') as ec_pub_file: pub_eckey = load_pem_public_key(ensure_bytes(ec_pub_file.read()), backend=default_backend()) self.jwt.decode(jwt_message, pub_eckey) # string-formatted key with open('tests/keys/testkey_ec', 'r') as ec_priv_file: priv_eckey = ec_priv_file.read() jwt_message = self.jwt.encode(self.payload, priv_eckey, algorithm='ES512') with open('tests/keys/testkey_ec.pub', 'r') as ec_pub_file: pub_eckey = ec_pub_file.read() self.jwt.decode(jwt_message, pub_eckey) def test_ecdsa_related_algorithms(self): self.jwt = PyJWT() jwt_algorithms = self.jwt.get_algorithms() if has_crypto: self.assertTrue('ES256' in jwt_algorithms) self.assertTrue('ES384' in jwt_algorithms) self.assertTrue('ES512' in jwt_algorithms) else: self.assertFalse('ES256' in jwt_algorithms) self.assertFalse('ES384' in jwt_algorithms) self.assertFalse('ES512' in jwt_algorithms) def test_check_audience_when_valid(self): payload = { 'some': 'payload', 'aud': 'urn:me' } token = self.jwt.encode(payload, 'secret') self.jwt.decode(token, 'secret', audience='urn:me') def test_check_audience_in_array_when_valid(self): payload = { 'some': 'payload', 'aud': ['urn:me', 'urn:someone-else'] } token = self.jwt.encode(payload, 'secret') self.jwt.decode(token, 'secret', audience='urn:me') def test_raise_exception_invalid_audience(self): payload = { 'some': 'payload', 'aud': 'urn:someone-else' } token = self.jwt.encode(payload, 'secret') with self.assertRaises(InvalidAudienceError): self.jwt.decode(token, 'secret', audience='urn-me') def test_raise_exception_invalid_audience_in_array(self): payload = { 'some': 'payload', 'aud': ['urn:someone', 'urn:someone-else'] } token = self.jwt.encode(payload, 'secret') with self.assertRaises(InvalidAudienceError): self.jwt.decode(token, 'secret', audience='urn:me') def test_raise_exception_token_without_audience(self): payload = { 'some': 'payload', } token = self.jwt.encode(payload, 'secret') with self.assertRaises(InvalidAudienceError): self.jwt.decode(token, 'secret', audience='urn:me') def test_check_issuer_when_valid(self): issuer = 'urn:foo' payload = { 'some': 'payload', 'iss': 'urn:foo' } token = self.jwt.encode(payload, 'secret') self.jwt.decode(token, 'secret', issuer=issuer) def test_raise_exception_invalid_issuer(self): issuer = 'urn:wrong' payload = { 'some': 'payload', 'iss': 'urn:foo' } token = self.jwt.encode(payload, 'secret') with self.assertRaises(InvalidIssuerError): self.jwt.decode(token, 'secret', issuer=issuer) def test_raise_exception_token_without_issuer(self): issuer = 'urn:wrong' payload = { 'some': 'payload', } token = self.jwt.encode(payload, 'secret') with self.assertRaises(InvalidIssuerError): self.jwt.decode(token, 'secret', issuer=issuer) def test_custom_json_encoder(self): class CustomJSONEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, Decimal): return 'it worked' return super(CustomJSONEncoder, self).default(o) data = { 'some_decimal': Decimal('2.2') } with self.assertRaises(TypeError): self.jwt.encode(data, 'secret') token = self.jwt.encode(data, 'secret', json_encoder=CustomJSONEncoder) payload = self.jwt.decode(token, 'secret') self.assertEqual(payload, {'some_decimal': 'it worked'})