def test_jwt_public_key_sign_verify(self, key_template_name): supported_langs = supported_key_types.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME[ key_template_name] self.assertNotEmpty(supported_langs) key_template = supported_key_types.KEY_TEMPLATE[key_template_name] # Take the first supported language to generate the private keyset. private_keyset = testing_servers.new_keyset(supported_langs[0], key_template) supported_signers = [ testing_servers.jwt_public_key_sign(lang, private_keyset) for lang in supported_langs ] unsupported_signers = [ testing_servers.jwt_public_key_sign(lang, private_keyset) for lang in SUPPORTED_LANGUAGES if lang not in supported_langs ] public_keyset = testing_servers.public_keyset('java', private_keyset) supported_verifiers = [ testing_servers.jwt_public_key_verify(lang, public_keyset) for lang in supported_langs ] unsupported_verifiers = [ testing_servers.jwt_public_key_verify(lang, public_keyset) for lang in SUPPORTED_LANGUAGES if lang not in supported_langs ] now = datetime.datetime.now(tz=datetime.timezone.utc) raw_jwt = jwt.new_raw_jwt( issuer='issuer', audiences=['audience1', 'audience2'], expiration=now + datetime.timedelta(seconds=100)) for signer in supported_signers: compact = signer.sign_and_encode(raw_jwt) validator = jwt.new_validator(audience='audience1', fixed_now=now) for verifier in supported_verifiers: verified_jwt = verifier.verify_and_decode(compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer') for verifier in unsupported_verifiers: with self.assertRaises( tink.TinkError, msg='%s supports jwt_public_key_verify with %s unexpectedly' % (verifier.lang, key_template_name)): verifier.verify_and_decode(compact, validator) for signer in unsupported_signers: with self.assertRaises( tink.TinkError, msg='%s supports jwt_public_key_sign with %s unexpectedly' % (signer.lang, key_template_name)): _ = signer.sign_and_encode(raw_jwt)
def test_jwt_public_key_sign_verify(self, lang): private_keyset = testing_servers.new_keyset(lang, jwt.jwt_es256_template()) public_keyset = testing_servers.public_keyset(lang, private_keyset) signer = testing_servers.jwt_public_key_sign(lang, private_keyset) verifier = testing_servers.jwt_public_key_verify(lang, public_keyset) now = datetime.datetime.now(tz=datetime.timezone.utc) token = jwt.new_raw_jwt( issuer='issuer', subject='subject', audiences=['audience1', 'audience2'], jwt_id='jwt_id', expiration=now + datetime.timedelta(seconds=10), custom_claims={'switch': True, 'pi': 3.14159}) compact = signer.sign_and_encode(token) validator = jwt.new_validator( expected_issuer='issuer', expected_audience='audience1', fixed_now=now) verified_jwt = verifier.verify_and_decode(compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer') self.assertEqual(verified_jwt.subject(), 'subject') self.assertEqual(verified_jwt.jwt_id(), 'jwt_id') self.assertEqual(verified_jwt.custom_claim('switch'), True) self.assertEqual(verified_jwt.custom_claim('pi'), 3.14159) validator2 = jwt.new_validator( expected_audience='wrong_audience', fixed_now=now) with self.assertRaises(tink.TinkError): verifier.verify_and_decode(compact, validator2)
def test_jwt_signature_without_primary(self, key_template_name, lang): """Unsets the primary key and tries to sign and verify JWT signatures.""" template = supported_key_types.KEY_TEMPLATE[key_template_name] private_keyset = testing_servers.new_keyset(lang, template) public_keyset = testing_servers.public_keyset(lang, private_keyset) signer = testing_servers.jwt_public_key_sign(lang, private_keyset) now = datetime.datetime.now(tz=datetime.timezone.utc) raw_jwt = jwt.new_raw_jwt(issuer='issuer', expiration=now + datetime.timedelta(seconds=100)) token = signer.sign_and_encode(raw_jwt) signer_without_primary = testing_servers.jwt_public_key_sign( lang, unset_primary(private_keyset)) with self.assertRaises(tink.TinkError): signer_without_primary.sign_and_encode(raw_jwt) verifier_without_primary = testing_servers.jwt_public_key_verify( lang, unset_primary(public_keyset)) validator = jwt.new_validator(expected_issuer='issuer', fixed_now=now) if lang in ['cc', 'java', 'python']: # C++, Java and Python currently allow this. verifier_without_primary.verify_and_decode(token, validator) else: with self.assertRaises(tink.TinkError): verifier_without_primary.verify_and_decode(token, validator)
def test_jwt_public_key_sign_verify(self, lang): key_format = jwt_ecdsa_pb2.JwtEcdsaKeyFormat( algorithm=jwt_ecdsa_pb2.ES256) key_template = tink_pb2.KeyTemplate( type_url='type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey', value=key_format.SerializeToString(), output_prefix_type=tink_pb2.RAW) private_keyset = testing_servers.new_keyset(lang, key_template) public_keyset = testing_servers.public_keyset(lang, private_keyset) signer = testing_servers.jwt_public_key_sign(lang, private_keyset) verifier = testing_servers.jwt_public_key_verify(lang, public_keyset) now = datetime.datetime.now(tz=datetime.timezone.utc) token = jwt.new_raw_jwt( issuer='issuer', subject='subject', audiences=['audience1', 'audience2'], jwt_id='jwt_id', expiration=now + datetime.timedelta(seconds=10), custom_claims={'switch': True, 'pi': 3.14159}) compact = signer.sign_and_encode(token) validator = jwt.new_validator(audience='audience1', fixed_now=now) verified_jwt = verifier.verify_and_decode(compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer') self.assertEqual(verified_jwt.subject(), 'subject') self.assertEqual(verified_jwt.jwt_id(), 'jwt_id') self.assertEqual(verified_jwt.custom_claim('switch'), True) self.assertEqual(verified_jwt.custom_claim('pi'), 3.14159) validator2 = jwt.new_validator(audience='wrong_audience', fixed_now=now) with self.assertRaises(tink.TinkError): verifier.verify_and_decode(compact, validator2)
def test_jwt_public_key_sign_export_import_verify(self, lang): private_keyset = testing_servers.new_keyset(lang, jwt.jwt_es256_template()) public_keyset = testing_servers.public_keyset(lang, private_keyset) # sign and export public key signer = testing_servers.jwt_public_key_sign(lang, private_keyset) now = datetime.datetime.now(tz=datetime.timezone.utc) token = jwt.new_raw_jwt( jwt_id='jwt_id', expiration=now + datetime.timedelta(seconds=100)) compact = signer.sign_and_encode(token) public_jwk_set = testing_servers.jwk_set_from_keyset(lang, public_keyset) # verify using public_jwk_set imported_public_keyset = testing_servers.jwk_set_to_keyset( lang, public_jwk_set) verifier = testing_servers.jwt_public_key_verify(lang, imported_public_keyset) validator = jwt.new_validator(fixed_now=now) verified_jwt = verifier.verify_and_decode(compact, validator) self.assertEqual(verified_jwt.jwt_id(), 'jwt_id')
def test_jwt_public_key_sign_export_import_verify(self, key_template_name): supported_langs = supported_key_types.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME[ key_template_name] self.assertNotEmpty(supported_langs) key_template = supported_key_types.KEY_TEMPLATE[key_template_name] # Take the first supported language to generate the private keyset. private_keyset = testing_servers.new_keyset(supported_langs[0], key_template) now = datetime.datetime.now(tz=datetime.timezone.utc) raw_jwt = jwt.new_raw_jwt(issuer='issuer', expiration=now + datetime.timedelta(seconds=100)) validator = jwt.new_validator(expected_issuer='issuer', fixed_now=now) for lang1 in supported_langs: # in lang1: sign token and export public keyset to a JWK set signer = testing_servers.jwt_public_key_sign(lang1, private_keyset) compact = signer.sign_and_encode(raw_jwt) public_keyset = testing_servers.public_keyset( lang1, private_keyset) public_jwk_set = testing_servers.jwk_set_from_keyset( lang1, public_keyset) for lang2 in supported_langs: # in lang2: import the public JWK set and verify the token public_keyset = testing_servers.jwk_set_to_keyset( lang2, public_jwk_set) verifier = testing_servers.jwt_public_key_verify( lang2, public_keyset) verified_jwt = verifier.verify_and_decode(compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer') # Additional tests for the "kid" property of the JWK and the "kid" # header of the token. Either of them may be missing, but they must not # have different values. jwks = json.loads(public_jwk_set) has_kid = 'kid' in jwks['keys'][0] if has_kid: # Change the "kid" property of the JWK. jwks['keys'][0]['kid'] = 'unknown kid' public_keyset = testing_servers.jwk_set_to_keyset( lang2, json.dumps(jwks)) verifier = testing_servers.jwt_public_key_verify( lang2, public_keyset) with self.assertRaises( tink.TinkError, msg= '%s accepts tokens with an incorrect kid unexpectedly' % lang2): verifier.verify_and_decode(compact, validator) # Remove the "kid" property of the JWK. del jwks['keys'][0]['kid'] public_keyset = testing_servers.jwk_set_to_keyset( lang2, json.dumps(jwks)) verifier = testing_servers.jwt_public_key_verify( lang2, public_keyset) verified_jwt = verifier.verify_and_decode( compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer') else: # Add a "kid" property of the JWK. jwks['keys'][0]['kid'] = 'unknown kid' public_keyset = testing_servers.jwk_set_to_keyset( lang2, json.dumps(jwks)) verifier = testing_servers.jwt_public_key_verify( lang2, public_keyset) verified_jwt = verifier.verify_and_decode( compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer')