1# Copyright 2021 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS-IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15# [START python-jwt-verify-example] 16"""A utility for verifying Json Web Tokens (JWT).""" 17 18import datetime 19 20from absl import app 21from absl import flags 22from absl import logging 23import tink 24from tink import jwt 25 26 27FLAGS = flags.FLAGS 28 29_PUBLIC_JWK_SET_PATH = flags.DEFINE_string( 30 'public_jwk_set_path', None, 'Path to public keyset in JWK set format.') 31_AUDIENCE = flags.DEFINE_string('audience', None, 32 'Audience to be used in the token') 33_TOKEN_PATH = flags.DEFINE_string('token_path', None, 34 'Path to the signature file.') 35 36 37def main(argv): 38 del argv # Unused. 39 40 # Initialise Tink 41 jwt.register_jwt_signature() 42 43 with open(_PUBLIC_JWK_SET_PATH.value, 'rt') as public_jwk_set_file: 44 try: 45 text = public_jwk_set_file.read() 46 keyset_handle = jwt.jwk_set_to_public_keyset_handle(text) 47 except tink.TinkError as e: 48 logging.exception('Error reading public JWK set: %s', e) 49 return 1 50 51 now = datetime.datetime.now(tz=datetime.timezone.utc) 52 try: 53 jwt_verify = keyset_handle.primitive(jwt.JwtPublicKeyVerify) 54 except tink.TinkError as e: 55 logging.exception('Error creating JwtPublicKeyVerify: %s', e) 56 return 1 57 58 # Verify token 59 with open(_TOKEN_PATH.value, 'rt') as token_file: 60 token = token_file.read() 61 validator = jwt.new_validator(expected_audience=_AUDIENCE.value) 62 try: 63 verified_jwt = jwt_verify.verify_and_decode(token, validator) 64 expires_in = verified_jwt.expiration() - now 65 logging.info('Token is valid and expires in %s seconds', expires_in.seconds) 66 return 0 67 except tink.TinkError as e: 68 logging.info('JWT verification failed: %s', e) 69 return 1 70 71 72if __name__ == '__main__': 73 flags.mark_flags_as_required(['audience', 'token_path']) 74 app.run(main) 75 76# [END python-jwt-verify-example] 77