1# Copyright 2020 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"""JSON Web Tokens 16 17Provides support for creating (encoding) and verifying (decoding) JWTs, 18especially JWTs generated and consumed by Google infrastructure. 19 20See `rfc7519`_ for more details on JWTs. 21 22To encode a JWT use :func:`encode`:: 23 24 from google.auth import crypt 25 from google.auth import jwt_async 26 27 signer = crypt.Signer(private_key) 28 payload = {'some': 'payload'} 29 encoded = jwt_async.encode(signer, payload) 30 31To decode a JWT and verify claims use :func:`decode`:: 32 33 claims = jwt_async.decode(encoded, certs=public_certs) 34 35You can also skip verification:: 36 37 claims = jwt_async.decode(encoded, verify=False) 38 39.. _rfc7519: https://tools.ietf.org/html/rfc7519 40 41 42NOTE: This async support is experimental and marked internal. This surface may 43change in minor releases. 44""" 45 46import google.auth 47from google.auth import jwt 48 49 50def encode(signer, payload, header=None, key_id=None): 51 """Make a signed JWT. 52 53 Args: 54 signer (google.auth.crypt.Signer): The signer used to sign the JWT. 55 payload (Mapping[str, str]): The JWT payload. 56 header (Mapping[str, str]): Additional JWT header payload. 57 key_id (str): The key id to add to the JWT header. If the 58 signer has a key id it will be used as the default. If this is 59 specified it will override the signer's key id. 60 61 Returns: 62 bytes: The encoded JWT. 63 """ 64 return jwt.encode(signer, payload, header, key_id) 65 66 67def decode(token, certs=None, verify=True, audience=None): 68 """Decode and verify a JWT. 69 70 Args: 71 token (str): The encoded JWT. 72 certs (Union[str, bytes, Mapping[str, Union[str, bytes]]]): The 73 certificate used to validate the JWT signature. If bytes or string, 74 it must the the public key certificate in PEM format. If a mapping, 75 it must be a mapping of key IDs to public key certificates in PEM 76 format. The mapping must contain the same key ID that's specified 77 in the token's header. 78 verify (bool): Whether to perform signature and claim validation. 79 Verification is done by default. 80 audience (str): The audience claim, 'aud', that this JWT should 81 contain. If None then the JWT's 'aud' parameter is not verified. 82 83 Returns: 84 Mapping[str, str]: The deserialized JSON payload in the JWT. 85 86 Raises: 87 ValueError: if any verification checks failed. 88 """ 89 90 return jwt.decode(token, certs, verify, audience) 91 92 93class Credentials( 94 jwt.Credentials, 95 google.auth._credentials_async.Signing, 96 google.auth._credentials_async.Credentials, 97): 98 """Credentials that use a JWT as the bearer token. 99 100 These credentials require an "audience" claim. This claim identifies the 101 intended recipient of the bearer token. 102 103 The constructor arguments determine the claims for the JWT that is 104 sent with requests. Usually, you'll construct these credentials with 105 one of the helper constructors as shown in the next section. 106 107 To create JWT credentials using a Google service account private key 108 JSON file:: 109 110 audience = 'https://pubsub.googleapis.com/google.pubsub.v1.Publisher' 111 credentials = jwt_async.Credentials.from_service_account_file( 112 'service-account.json', 113 audience=audience) 114 115 If you already have the service account file loaded and parsed:: 116 117 service_account_info = json.load(open('service_account.json')) 118 credentials = jwt_async.Credentials.from_service_account_info( 119 service_account_info, 120 audience=audience) 121 122 Both helper methods pass on arguments to the constructor, so you can 123 specify the JWT claims:: 124 125 credentials = jwt_async.Credentials.from_service_account_file( 126 'service-account.json', 127 audience=audience, 128 additional_claims={'meta': 'data'}) 129 130 You can also construct the credentials directly if you have a 131 :class:`~google.auth.crypt.Signer` instance:: 132 133 credentials = jwt_async.Credentials( 134 signer, 135 issuer='your-issuer', 136 subject='your-subject', 137 audience=audience) 138 139 The claims are considered immutable. If you want to modify the claims, 140 you can easily create another instance using :meth:`with_claims`:: 141 142 new_audience = ( 143 'https://pubsub.googleapis.com/google.pubsub.v1.Subscriber') 144 new_credentials = credentials.with_claims(audience=new_audience) 145 """ 146 147 148class OnDemandCredentials( 149 jwt.OnDemandCredentials, 150 google.auth._credentials_async.Signing, 151 google.auth._credentials_async.Credentials, 152): 153 """On-demand JWT credentials. 154 155 Like :class:`Credentials`, this class uses a JWT as the bearer token for 156 authentication. However, this class does not require the audience at 157 construction time. Instead, it will generate a new token on-demand for 158 each request using the request URI as the audience. It caches tokens 159 so that multiple requests to the same URI do not incur the overhead 160 of generating a new token every time. 161 162 This behavior is especially useful for `gRPC`_ clients. A gRPC service may 163 have multiple audience and gRPC clients may not know all of the audiences 164 required for accessing a particular service. With these credentials, 165 no knowledge of the audiences is required ahead of time. 166 167 .. _grpc: http://www.grpc.io/ 168 """ 169