1*e7b1675dSTing-Kang Chang# Copyright 2021 Google LLC 2*e7b1675dSTing-Kang Chang# 3*e7b1675dSTing-Kang Chang# Licensed under the Apache License, Version 2.0 (the "License"); 4*e7b1675dSTing-Kang Chang# you may not use this file except in compliance with the License. 5*e7b1675dSTing-Kang Chang# You may obtain a copy of the License at 6*e7b1675dSTing-Kang Chang# 7*e7b1675dSTing-Kang Chang# http://www.apache.org/licenses/LICENSE-2.0 8*e7b1675dSTing-Kang Chang# 9*e7b1675dSTing-Kang Chang# Unless required by applicable law or agreed to in writing, software 10*e7b1675dSTing-Kang Chang# distributed under the License is distributed on an "AS-IS" BASIS, 11*e7b1675dSTing-Kang Chang# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*e7b1675dSTing-Kang Chang# See the License for the specific language governing permissions and 13*e7b1675dSTing-Kang Chang# limitations under the License. 14*e7b1675dSTing-Kang Chang"""Tests for tink.testing.python.jwt_service.""" 15*e7b1675dSTing-Kang Chang 16*e7b1675dSTing-Kang Changfrom absl.testing import absltest 17*e7b1675dSTing-Kang Changimport grpc 18*e7b1675dSTing-Kang Chang 19*e7b1675dSTing-Kang Changfrom tink import jwt 20*e7b1675dSTing-Kang Chang 21*e7b1675dSTing-Kang Changfrom protos import testing_api_pb2 22*e7b1675dSTing-Kang Changimport jwt_service 23*e7b1675dSTing-Kang Changimport services 24*e7b1675dSTing-Kang Chang 25*e7b1675dSTing-Kang Chang 26*e7b1675dSTing-Kang Changclass DummyServicerContext(grpc.ServicerContext): 27*e7b1675dSTing-Kang Chang 28*e7b1675dSTing-Kang Chang def is_active(self): 29*e7b1675dSTing-Kang Chang pass 30*e7b1675dSTing-Kang Chang 31*e7b1675dSTing-Kang Chang def time_remaining(self): 32*e7b1675dSTing-Kang Chang pass 33*e7b1675dSTing-Kang Chang 34*e7b1675dSTing-Kang Chang def cancel(self): 35*e7b1675dSTing-Kang Chang pass 36*e7b1675dSTing-Kang Chang 37*e7b1675dSTing-Kang Chang def add_callback(self, callback): 38*e7b1675dSTing-Kang Chang pass 39*e7b1675dSTing-Kang Chang 40*e7b1675dSTing-Kang Chang def invocation_metadata(self): 41*e7b1675dSTing-Kang Chang pass 42*e7b1675dSTing-Kang Chang 43*e7b1675dSTing-Kang Chang def peer(self): 44*e7b1675dSTing-Kang Chang pass 45*e7b1675dSTing-Kang Chang 46*e7b1675dSTing-Kang Chang def peer_identities(self): 47*e7b1675dSTing-Kang Chang pass 48*e7b1675dSTing-Kang Chang 49*e7b1675dSTing-Kang Chang def peer_identity_key(self): 50*e7b1675dSTing-Kang Chang pass 51*e7b1675dSTing-Kang Chang 52*e7b1675dSTing-Kang Chang def auth_context(self): 53*e7b1675dSTing-Kang Chang pass 54*e7b1675dSTing-Kang Chang 55*e7b1675dSTing-Kang Chang def set_compression(self, compression): 56*e7b1675dSTing-Kang Chang pass 57*e7b1675dSTing-Kang Chang 58*e7b1675dSTing-Kang Chang def send_initial_metadata(self, initial_metadata): 59*e7b1675dSTing-Kang Chang pass 60*e7b1675dSTing-Kang Chang 61*e7b1675dSTing-Kang Chang def set_trailing_metadata(self, trailing_metadata): 62*e7b1675dSTing-Kang Chang pass 63*e7b1675dSTing-Kang Chang 64*e7b1675dSTing-Kang Chang def abort(self, code, details): 65*e7b1675dSTing-Kang Chang pass 66*e7b1675dSTing-Kang Chang 67*e7b1675dSTing-Kang Chang def abort_with_status(self, status): 68*e7b1675dSTing-Kang Chang pass 69*e7b1675dSTing-Kang Chang 70*e7b1675dSTing-Kang Chang def set_code(self, code): 71*e7b1675dSTing-Kang Chang pass 72*e7b1675dSTing-Kang Chang 73*e7b1675dSTing-Kang Chang def set_details(self, details): 74*e7b1675dSTing-Kang Chang pass 75*e7b1675dSTing-Kang Chang 76*e7b1675dSTing-Kang Chang def disable_next_message_compression(self): 77*e7b1675dSTing-Kang Chang pass 78*e7b1675dSTing-Kang Chang 79*e7b1675dSTing-Kang Chang 80*e7b1675dSTing-Kang Changclass JwtServiceTest(absltest.TestCase): 81*e7b1675dSTing-Kang Chang 82*e7b1675dSTing-Kang Chang _ctx = DummyServicerContext() 83*e7b1675dSTing-Kang Chang 84*e7b1675dSTing-Kang Chang @classmethod 85*e7b1675dSTing-Kang Chang def setUpClass(cls): 86*e7b1675dSTing-Kang Chang super().setUpClass() 87*e7b1675dSTing-Kang Chang jwt.register_jwt_mac() 88*e7b1675dSTing-Kang Chang jwt.register_jwt_signature() 89*e7b1675dSTing-Kang Chang 90*e7b1675dSTing-Kang Chang def test_create_jwt_mac(self): 91*e7b1675dSTing-Kang Chang keyset_servicer = services.KeysetServicer() 92*e7b1675dSTing-Kang Chang jwt_servicer = jwt_service.JwtServicer() 93*e7b1675dSTing-Kang Chang 94*e7b1675dSTing-Kang Chang template = jwt.jwt_hs256_template().SerializeToString() 95*e7b1675dSTing-Kang Chang gen_request = testing_api_pb2.KeysetGenerateRequest(template=template) 96*e7b1675dSTing-Kang Chang gen_response = keyset_servicer.Generate(gen_request, self._ctx) 97*e7b1675dSTing-Kang Chang self.assertEqual(gen_response.WhichOneof('result'), 'keyset') 98*e7b1675dSTing-Kang Chang 99*e7b1675dSTing-Kang Chang creation_request = testing_api_pb2.CreationRequest( 100*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 101*e7b1675dSTing-Kang Chang serialized_keyset=gen_response.keyset)) 102*e7b1675dSTing-Kang Chang creation_response = jwt_servicer.CreateJwtMac( 103*e7b1675dSTing-Kang Chang creation_request, self._ctx) 104*e7b1675dSTing-Kang Chang self.assertEmpty(creation_response.err) 105*e7b1675dSTing-Kang Chang 106*e7b1675dSTing-Kang Chang def test_create_jwt_mac_broken_keyset(self): 107*e7b1675dSTing-Kang Chang jwt_servicer = jwt_service.JwtServicer() 108*e7b1675dSTing-Kang Chang 109*e7b1675dSTing-Kang Chang creation_request = testing_api_pb2.CreationRequest( 110*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 111*e7b1675dSTing-Kang Chang serialized_keyset=b'\x80')) 112*e7b1675dSTing-Kang Chang creation_response = jwt_servicer.CreateJwtMac(creation_request, self._ctx) 113*e7b1675dSTing-Kang Chang self.assertNotEmpty(creation_response.err) 114*e7b1675dSTing-Kang Chang 115*e7b1675dSTing-Kang Chang def test_generate_compute_verify_mac(self): 116*e7b1675dSTing-Kang Chang keyset_servicer = services.KeysetServicer() 117*e7b1675dSTing-Kang Chang jwt_servicer = jwt_service.JwtServicer() 118*e7b1675dSTing-Kang Chang 119*e7b1675dSTing-Kang Chang template = jwt.jwt_hs256_template().SerializeToString() 120*e7b1675dSTing-Kang Chang gen_request = testing_api_pb2.KeysetGenerateRequest(template=template) 121*e7b1675dSTing-Kang Chang gen_response = keyset_servicer.Generate(gen_request, self._ctx) 122*e7b1675dSTing-Kang Chang self.assertEqual(gen_response.WhichOneof('result'), 'keyset') 123*e7b1675dSTing-Kang Chang keyset = gen_response.keyset 124*e7b1675dSTing-Kang Chang 125*e7b1675dSTing-Kang Chang comp_request = testing_api_pb2.JwtSignRequest( 126*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 127*e7b1675dSTing-Kang Chang serialized_keyset=keyset)) 128*e7b1675dSTing-Kang Chang comp_request.raw_jwt.issuer.value = 'issuer' 129*e7b1675dSTing-Kang Chang comp_request.raw_jwt.subject.value = 'subject' 130*e7b1675dSTing-Kang Chang comp_request.raw_jwt.custom_claims['myclaim'].bool_value = True 131*e7b1675dSTing-Kang Chang comp_request.raw_jwt.expiration.seconds = 1334 132*e7b1675dSTing-Kang Chang comp_request.raw_jwt.expiration.nanos = 123000000 133*e7b1675dSTing-Kang Chang 134*e7b1675dSTing-Kang Chang comp_response = jwt_servicer.ComputeMacAndEncode(comp_request, self._ctx) 135*e7b1675dSTing-Kang Chang self.assertEqual(comp_response.WhichOneof('result'), 'signed_compact_jwt') 136*e7b1675dSTing-Kang Chang signed_compact_jwt = comp_response.signed_compact_jwt 137*e7b1675dSTing-Kang Chang verify_request = testing_api_pb2.JwtVerifyRequest( 138*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 139*e7b1675dSTing-Kang Chang serialized_keyset=keyset), 140*e7b1675dSTing-Kang Chang signed_compact_jwt=signed_compact_jwt) 141*e7b1675dSTing-Kang Chang verify_request.validator.expected_issuer.value = 'issuer' 142*e7b1675dSTing-Kang Chang verify_request.validator.now.seconds = 1234 143*e7b1675dSTing-Kang Chang verify_response = jwt_servicer.VerifyMacAndDecode(verify_request, self._ctx) 144*e7b1675dSTing-Kang Chang self.assertEqual(verify_response.WhichOneof('result'), 'verified_jwt') 145*e7b1675dSTing-Kang Chang self.assertEqual(verify_response.verified_jwt.issuer.value, 'issuer') 146*e7b1675dSTing-Kang Chang self.assertEqual(verify_response.verified_jwt.subject.value, 'subject') 147*e7b1675dSTing-Kang Chang self.assertEqual(verify_response.verified_jwt.expiration.seconds, 1334) 148*e7b1675dSTing-Kang Chang self.assertEqual(verify_response.verified_jwt.expiration.nanos, 0) 149*e7b1675dSTing-Kang Chang 150*e7b1675dSTing-Kang Chang def test_generate_compute_verify_mac_without_expiration(self): 151*e7b1675dSTing-Kang Chang keyset_servicer = services.KeysetServicer() 152*e7b1675dSTing-Kang Chang jwt_servicer = jwt_service.JwtServicer() 153*e7b1675dSTing-Kang Chang 154*e7b1675dSTing-Kang Chang template = jwt.jwt_hs256_template().SerializeToString() 155*e7b1675dSTing-Kang Chang gen_request = testing_api_pb2.KeysetGenerateRequest(template=template) 156*e7b1675dSTing-Kang Chang gen_response = keyset_servicer.Generate(gen_request, self._ctx) 157*e7b1675dSTing-Kang Chang self.assertEqual(gen_response.WhichOneof('result'), 'keyset') 158*e7b1675dSTing-Kang Chang keyset = gen_response.keyset 159*e7b1675dSTing-Kang Chang 160*e7b1675dSTing-Kang Chang comp_request = testing_api_pb2.JwtSignRequest( 161*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 162*e7b1675dSTing-Kang Chang serialized_keyset=keyset)) 163*e7b1675dSTing-Kang Chang comp_request.raw_jwt.issuer.value = 'issuer' 164*e7b1675dSTing-Kang Chang 165*e7b1675dSTing-Kang Chang comp_response = jwt_servicer.ComputeMacAndEncode(comp_request, self._ctx) 166*e7b1675dSTing-Kang Chang self.assertEqual(comp_response.WhichOneof('result'), 'signed_compact_jwt') 167*e7b1675dSTing-Kang Chang signed_compact_jwt = comp_response.signed_compact_jwt 168*e7b1675dSTing-Kang Chang verify_request = testing_api_pb2.JwtVerifyRequest( 169*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 170*e7b1675dSTing-Kang Chang serialized_keyset=keyset), 171*e7b1675dSTing-Kang Chang signed_compact_jwt=signed_compact_jwt) 172*e7b1675dSTing-Kang Chang verify_request.validator.expected_issuer.value = 'issuer' 173*e7b1675dSTing-Kang Chang verify_request.validator.allow_missing_expiration = True 174*e7b1675dSTing-Kang Chang verify_response = jwt_servicer.VerifyMacAndDecode(verify_request, self._ctx) 175*e7b1675dSTing-Kang Chang print(verify_response.err) 176*e7b1675dSTing-Kang Chang self.assertEqual(verify_response.WhichOneof('result'), 'verified_jwt') 177*e7b1675dSTing-Kang Chang self.assertEqual(verify_response.verified_jwt.issuer.value, 'issuer') 178*e7b1675dSTing-Kang Chang 179*e7b1675dSTing-Kang Chang def test_create_public_key_sign(self): 180*e7b1675dSTing-Kang Chang keyset_servicer = services.KeysetServicer() 181*e7b1675dSTing-Kang Chang jwt_servicer = jwt_service.JwtServicer() 182*e7b1675dSTing-Kang Chang 183*e7b1675dSTing-Kang Chang template = jwt.jwt_es256_template().SerializeToString() 184*e7b1675dSTing-Kang Chang gen_request = testing_api_pb2.KeysetGenerateRequest(template=template) 185*e7b1675dSTing-Kang Chang gen_response = keyset_servicer.Generate(gen_request, self._ctx) 186*e7b1675dSTing-Kang Chang self.assertEqual(gen_response.WhichOneof('result'), 'keyset') 187*e7b1675dSTing-Kang Chang 188*e7b1675dSTing-Kang Chang creation_request = testing_api_pb2.CreationRequest( 189*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 190*e7b1675dSTing-Kang Chang serialized_keyset=gen_response.keyset)) 191*e7b1675dSTing-Kang Chang creation_response = jwt_servicer.CreateJwtPublicKeySign( 192*e7b1675dSTing-Kang Chang creation_request, self._ctx) 193*e7b1675dSTing-Kang Chang self.assertEmpty(creation_response.err) 194*e7b1675dSTing-Kang Chang 195*e7b1675dSTing-Kang Chang def test_create_public_key_sign_bad_keyset(self): 196*e7b1675dSTing-Kang Chang jwt_servicer = jwt_service.JwtServicer() 197*e7b1675dSTing-Kang Chang 198*e7b1675dSTing-Kang Chang creation_request = testing_api_pb2.CreationRequest( 199*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 200*e7b1675dSTing-Kang Chang serialized_keyset=b'\x80')) 201*e7b1675dSTing-Kang Chang creation_response = jwt_servicer.CreateJwtPublicKeySign( 202*e7b1675dSTing-Kang Chang creation_request, self._ctx) 203*e7b1675dSTing-Kang Chang self.assertNotEmpty(creation_response.err) 204*e7b1675dSTing-Kang Chang 205*e7b1675dSTing-Kang Chang def test_create_public_key_verify(self): 206*e7b1675dSTing-Kang Chang keyset_servicer = services.KeysetServicer() 207*e7b1675dSTing-Kang Chang jwt_servicer = jwt_service.JwtServicer() 208*e7b1675dSTing-Kang Chang 209*e7b1675dSTing-Kang Chang template = jwt.jwt_es256_template().SerializeToString() 210*e7b1675dSTing-Kang Chang gen_request = testing_api_pb2.KeysetGenerateRequest(template=template) 211*e7b1675dSTing-Kang Chang gen_response = keyset_servicer.Generate(gen_request, self._ctx) 212*e7b1675dSTing-Kang Chang self.assertEqual(gen_response.WhichOneof('result'), 'keyset') 213*e7b1675dSTing-Kang Chang pub_request = testing_api_pb2.KeysetPublicRequest( 214*e7b1675dSTing-Kang Chang private_keyset=gen_response.keyset) 215*e7b1675dSTing-Kang Chang pub_response = keyset_servicer.Public(pub_request, self._ctx) 216*e7b1675dSTing-Kang Chang self.assertEqual(pub_response.WhichOneof('result'), 'public_keyset') 217*e7b1675dSTing-Kang Chang 218*e7b1675dSTing-Kang Chang creation_request = testing_api_pb2.CreationRequest( 219*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 220*e7b1675dSTing-Kang Chang serialized_keyset=pub_response.public_keyset)) 221*e7b1675dSTing-Kang Chang creation_response = jwt_servicer.CreateJwtPublicKeyVerify( 222*e7b1675dSTing-Kang Chang creation_request, self._ctx) 223*e7b1675dSTing-Kang Chang self.assertEmpty(creation_response.err) 224*e7b1675dSTing-Kang Chang 225*e7b1675dSTing-Kang Chang def test_create_public_key_verify_bad_keyset(self): 226*e7b1675dSTing-Kang Chang jwt_servicer = jwt_service.JwtServicer() 227*e7b1675dSTing-Kang Chang 228*e7b1675dSTing-Kang Chang creation_request = testing_api_pb2.CreationRequest( 229*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 230*e7b1675dSTing-Kang Chang serialized_keyset=b'\x80')) 231*e7b1675dSTing-Kang Chang creation_response = jwt_servicer.CreateJwtPublicKeyVerify( 232*e7b1675dSTing-Kang Chang creation_request, self._ctx) 233*e7b1675dSTing-Kang Chang self.assertNotEmpty(creation_response.err) 234*e7b1675dSTing-Kang Chang 235*e7b1675dSTing-Kang Chang def test_generate_sign_export_import_verify_signature(self): 236*e7b1675dSTing-Kang Chang keyset_servicer = services.KeysetServicer() 237*e7b1675dSTing-Kang Chang jwt_servicer = jwt_service.JwtServicer() 238*e7b1675dSTing-Kang Chang 239*e7b1675dSTing-Kang Chang template = jwt.jwt_es256_template().SerializeToString() 240*e7b1675dSTing-Kang Chang gen_request = testing_api_pb2.KeysetGenerateRequest(template=template) 241*e7b1675dSTing-Kang Chang gen_response = keyset_servicer.Generate(gen_request, self._ctx) 242*e7b1675dSTing-Kang Chang self.assertEqual(gen_response.WhichOneof('result'), 'keyset') 243*e7b1675dSTing-Kang Chang private_keyset = gen_response.keyset 244*e7b1675dSTing-Kang Chang 245*e7b1675dSTing-Kang Chang comp_request = testing_api_pb2.JwtSignRequest( 246*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 247*e7b1675dSTing-Kang Chang serialized_keyset=private_keyset)) 248*e7b1675dSTing-Kang Chang comp_request.raw_jwt.issuer.value = 'issuer' 249*e7b1675dSTing-Kang Chang comp_request.raw_jwt.subject.value = 'subject' 250*e7b1675dSTing-Kang Chang comp_request.raw_jwt.custom_claims['myclaim'].bool_value = True 251*e7b1675dSTing-Kang Chang comp_response = jwt_servicer.PublicKeySignAndEncode(comp_request, self._ctx) 252*e7b1675dSTing-Kang Chang self.assertEqual(comp_response.WhichOneof('result'), 'signed_compact_jwt') 253*e7b1675dSTing-Kang Chang signed_compact_jwt = comp_response.signed_compact_jwt 254*e7b1675dSTing-Kang Chang 255*e7b1675dSTing-Kang Chang pub_request = testing_api_pb2.KeysetPublicRequest( 256*e7b1675dSTing-Kang Chang private_keyset=private_keyset) 257*e7b1675dSTing-Kang Chang pub_response = keyset_servicer.Public(pub_request, self._ctx) 258*e7b1675dSTing-Kang Chang self.assertEqual(pub_response.WhichOneof('result'), 'public_keyset') 259*e7b1675dSTing-Kang Chang public_keyset = pub_response.public_keyset 260*e7b1675dSTing-Kang Chang 261*e7b1675dSTing-Kang Chang to_jwkset_request = testing_api_pb2.JwtToJwkSetRequest(keyset=public_keyset) 262*e7b1675dSTing-Kang Chang to_jwkset_response = jwt_servicer.ToJwkSet(to_jwkset_request, self._ctx) 263*e7b1675dSTing-Kang Chang self.assertEqual(to_jwkset_response.WhichOneof('result'), 'jwk_set') 264*e7b1675dSTing-Kang Chang 265*e7b1675dSTing-Kang Chang self.assertStartsWith(to_jwkset_response.jwk_set, '{"keys":[{"') 266*e7b1675dSTing-Kang Chang 267*e7b1675dSTing-Kang Chang from_jwkset_request = testing_api_pb2.JwtFromJwkSetRequest( 268*e7b1675dSTing-Kang Chang jwk_set=to_jwkset_response.jwk_set) 269*e7b1675dSTing-Kang Chang from_jwkset_response = jwt_servicer.FromJwkSet( 270*e7b1675dSTing-Kang Chang from_jwkset_request, self._ctx) 271*e7b1675dSTing-Kang Chang self.assertEqual(from_jwkset_response.WhichOneof('result'), 'keyset') 272*e7b1675dSTing-Kang Chang 273*e7b1675dSTing-Kang Chang verify_request = testing_api_pb2.JwtVerifyRequest( 274*e7b1675dSTing-Kang Chang annotated_keyset=testing_api_pb2.AnnotatedKeyset( 275*e7b1675dSTing-Kang Chang serialized_keyset=from_jwkset_response.keyset), 276*e7b1675dSTing-Kang Chang signed_compact_jwt=signed_compact_jwt) 277*e7b1675dSTing-Kang Chang verify_request.validator.expected_issuer.value = 'issuer' 278*e7b1675dSTing-Kang Chang verify_request.validator.allow_missing_expiration = True 279*e7b1675dSTing-Kang Chang verify_response = jwt_servicer.PublicKeyVerifyAndDecode( 280*e7b1675dSTing-Kang Chang verify_request, self._ctx) 281*e7b1675dSTing-Kang Chang self.assertEqual(verify_response.WhichOneof('result'), 'verified_jwt') 282*e7b1675dSTing-Kang Chang self.assertEqual(verify_response.verified_jwt.issuer.value, 'issuer') 283*e7b1675dSTing-Kang Chang 284*e7b1675dSTing-Kang Chang def test_to_jwk_set_with_invalid_keyset_fails(self): 285*e7b1675dSTing-Kang Chang jwt_servicer = jwt_service.JwtServicer() 286*e7b1675dSTing-Kang Chang 287*e7b1675dSTing-Kang Chang to_jwkset_request = testing_api_pb2.JwtToJwkSetRequest(keyset=b'invalid') 288*e7b1675dSTing-Kang Chang jwkset_response = jwt_servicer.ToJwkSet(to_jwkset_request, self._ctx) 289*e7b1675dSTing-Kang Chang self.assertEqual(jwkset_response.WhichOneof('result'), 'err') 290*e7b1675dSTing-Kang Chang 291*e7b1675dSTing-Kang Chang def test_from_jwk_set_with_invalid_jwk_set_fails(self): 292*e7b1675dSTing-Kang Chang jwt_servicer = jwt_service.JwtServicer() 293*e7b1675dSTing-Kang Chang 294*e7b1675dSTing-Kang Chang from_jwkset_request = testing_api_pb2.JwtFromJwkSetRequest( 295*e7b1675dSTing-Kang Chang jwk_set='invalid') 296*e7b1675dSTing-Kang Chang from_jwkset_response = jwt_servicer.FromJwkSet(from_jwkset_request, 297*e7b1675dSTing-Kang Chang self._ctx) 298*e7b1675dSTing-Kang Chang self.assertEqual(from_jwkset_response.WhichOneof('result'), 'err') 299*e7b1675dSTing-Kang Chang print(from_jwkset_response.err) 300*e7b1675dSTing-Kang Chang 301*e7b1675dSTing-Kang Chang 302*e7b1675dSTing-Kang Changif __name__ == '__main__': 303*e7b1675dSTing-Kang Chang absltest.main() 304