blob: 54630d34ba989eda4a11ff56e3fd79165922eed9 [file] [log] [blame]
C.J. Collier37141e42020-02-13 13:49:49 -08001# Copyright 2016 Google LLC
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -07002#
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"""Service Accounts: JSON Web Token (JWT) Profile for OAuth 2.0
16
17This module implements the JWT Profile for OAuth 2.0 Authorization Grants
18as defined by `RFC 7523`_ with particular support for how this RFC is
19implemented in Google's infrastructure. Google refers to these credentials
20as *Service Accounts*.
21
22Service accounts are used for server-to-server communication, such as
23interactions between a web application server and a Google service. The
24service account belongs to your application instead of to an individual end
25user. In contrast to other OAuth 2.0 profiles, no users are involved and your
26application "acts" as the service account.
27
28Typically an application uses a service account when the application uses
29Google APIs to work with its own data rather than a user's data. For example,
30an application that uses Google Cloud Datastore for data persistence would use
31a service account to authenticate its calls to the Google Cloud Datastore API.
32However, an application that needs to access a user's Drive documents would
33use the normal OAuth 2.0 profile.
34
35Additionally, Google Apps domain administrators can grant service accounts
36`domain-wide delegation`_ authority to access user data on behalf of users in
37the domain.
38
39This profile uses a JWT to acquire an OAuth 2.0 access token. The JWT is used
40in place of the usual authorization token returned during the standard
41OAuth 2.0 Authorization Code grant. The JWT is only used for this purpose, as
42the acquired access token is used as the bearer token when making requests
43using these credentials.
44
45This profile differs from normal OAuth 2.0 profile because no user consent
46step is required. The use of the private key allows this profile to assert
47identity directly.
48
49This profile also differs from the :mod:`google.auth.jwt` authentication
50because the JWT credentials use the JWT directly as the bearer token. This
51profile instead only uses the JWT to obtain an OAuth 2.0 access token. The
52obtained OAuth 2.0 access token is used as the bearer token.
53
54Domain-wide delegation
55----------------------
56
57Domain-wide delegation allows a service account to access user data on
58behalf of any user in a Google Apps domain without consent from the user.
59For example, an application that uses the Google Calendar API to add events to
60the calendars of all users in a Google Apps domain would use a service account
61to access the Google Calendar API on behalf of users.
62
63The Google Apps administrator must explicitly authorize the service account to
64do this. This authorization step is referred to as "delegating domain-wide
65authority" to a service account.
66
67You can use domain-wise delegation by creating a set of credentials with a
68specific subject using :meth:`~Credentials.with_subject`.
69
70.. _RFC 7523: https://tools.ietf.org/html/rfc7523
71"""
72
Jon Wayne Parrott75c78b22017-03-23 13:14:53 -070073import copy
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -070074import datetime
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -070075
76from google.auth import _helpers
Jon Wayne Parrott807032c2016-10-18 09:38:26 -070077from google.auth import _service_account_info
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -070078from google.auth import credentials
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -070079from google.auth import jwt
80from google.oauth2 import _client
81
Albert-Jan Nijburgb7b48f12017-11-08 20:15:18 +000082_DEFAULT_TOKEN_LIFETIME_SECS = 3600 # 1 hour in seconds
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -070083
84
Bu Sun Kim9eec0912019-10-21 17:04:21 -070085class Credentials(credentials.Signing, credentials.Scoped, credentials.Credentials):
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -070086 """Service account credentials
87
88 Usually, you'll create these credentials with one of the helper
89 constructors. To create credentials using a Google service account
90 private key JSON file::
91
92 credentials = service_account.Credentials.from_service_account_file(
93 'service-account.json')
94
95 Or if you already have the service account file loaded::
96
97 service_account_info = json.load(open('service_account.json'))
98 credentials = service_account.Credentials.from_service_account_info(
99 service_account_info)
100
101 Both helper methods pass on arguments to the constructor, so you can
102 specify additional scopes and a subject if necessary::
103
104 credentials = service_account.Credentials.from_service_account_file(
105 'service-account.json',
106 scopes=['email'],
107 subject='user@example.com')
108
109 The credentials are considered immutable. If you want to modify the scopes
110 or the subject used for delegation, use :meth:`with_scopes` or
111 :meth:`with_subject`::
112
113 scoped_credentials = credentials.with_scopes(['email'])
114 delegated_credentials = credentials.with_subject(subject)
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700115
116 To add a quota project, use :meth:`with_quota_project`::
117
118 credentials = credentials.with_quota_project('myproject-123')
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700119 """
120
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700121 def __init__(
122 self,
123 signer,
124 service_account_email,
125 token_uri,
126 scopes=None,
127 subject=None,
128 project_id=None,
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700129 quota_project_id=None,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700130 additional_claims=None,
131 ):
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700132 """
133 Args:
134 signer (google.auth.crypt.Signer): The signer used to sign JWTs.
135 service_account_email (str): The service account's email.
136 scopes (Sequence[str]): Scopes to request during the authorization
137 grant.
138 token_uri (str): The OAuth 2.0 Token URI.
139 subject (str): For domain-wide delegation, the email address of the
140 user to for which to request delegated access.
Hiranya Jayathilaka6a3f0ec2017-08-10 09:11:02 -0700141 project_id (str): Project ID associated with the service account
142 credential.
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700143 quota_project_id (Optional[str]): The project ID used for quota and
144 billing.
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700145 additional_claims (Mapping[str, str]): Any additional claims for
146 the JWT assertion used in the authorization grant.
147
148 .. note:: Typically one of the helper constructors
149 :meth:`from_service_account_file` or
150 :meth:`from_service_account_info` are used instead of calling the
151 constructor directly.
152 """
153 super(Credentials, self).__init__()
154
155 self._scopes = scopes
156 self._signer = signer
157 self._service_account_email = service_account_email
158 self._subject = subject
Hiranya Jayathilaka6a3f0ec2017-08-10 09:11:02 -0700159 self._project_id = project_id
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700160 self._quota_project_id = quota_project_id
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700161 self._token_uri = token_uri
162
163 if additional_claims is not None:
164 self._additional_claims = additional_claims
165 else:
166 self._additional_claims = {}
167
168 @classmethod
Jon Wayne Parrott807032c2016-10-18 09:38:26 -0700169 def _from_signer_and_info(cls, signer, info, **kwargs):
170 """Creates a Credentials instance from a signer and service account
171 info.
172
173 Args:
174 signer (google.auth.crypt.Signer): The signer used to sign JWTs.
175 info (Mapping[str, str]): The service account info.
176 kwargs: Additional arguments to pass to the constructor.
177
178 Returns:
179 google.auth.jwt.Credentials: The constructed credentials.
180
181 Raises:
182 ValueError: If the info is not in the expected format.
183 """
184 return cls(
185 signer,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700186 service_account_email=info["client_email"],
187 token_uri=info["token_uri"],
188 project_id=info.get("project_id"),
189 **kwargs
190 )
Jon Wayne Parrott807032c2016-10-18 09:38:26 -0700191
192 @classmethod
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700193 def from_service_account_info(cls, info, **kwargs):
194 """Creates a Credentials instance from parsed service account info.
195
196 Args:
197 info (Mapping[str, str]): The service account info in Google
198 format.
199 kwargs: Additional arguments to pass to the constructor.
200
201 Returns:
202 google.auth.service_account.Credentials: The constructed
203 credentials.
204
205 Raises:
206 ValueError: If the info is not in the expected format.
207 """
Jon Wayne Parrott807032c2016-10-18 09:38:26 -0700208 signer = _service_account_info.from_dict(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700209 info, require=["client_email", "token_uri"]
210 )
Jon Wayne Parrott807032c2016-10-18 09:38:26 -0700211 return cls._from_signer_and_info(signer, info, **kwargs)
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700212
213 @classmethod
214 def from_service_account_file(cls, filename, **kwargs):
215 """Creates a Credentials instance from a service account json file.
216
217 Args:
218 filename (str): The path to the service account json file.
219 kwargs: Additional arguments to pass to the constructor.
220
221 Returns:
222 google.auth.service_account.Credentials: The constructed
223 credentials.
224 """
Jon Wayne Parrott807032c2016-10-18 09:38:26 -0700225 info, signer = _service_account_info.from_filename(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700226 filename, require=["client_email", "token_uri"]
227 )
Jon Wayne Parrott807032c2016-10-18 09:38:26 -0700228 return cls._from_signer_and_info(signer, info, **kwargs)
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700229
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700230 @property
Jon Wayne Parrott61ffb052016-11-08 09:30:30 -0800231 def service_account_email(self):
232 """The service account email."""
233 return self._service_account_email
234
235 @property
Hiranya Jayathilaka6a3f0ec2017-08-10 09:11:02 -0700236 def project_id(self):
237 """Project ID associated with this credential."""
238 return self._project_id
239
240 @property
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700241 def quota_project_id(self):
242 """Project ID to use for quota and billing purposes."""
243 return self._quota_project_id
244
245 @property
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700246 def requires_scopes(self):
247 """Checks if the credentials requires scopes.
248
249 Returns:
250 bool: True if there are no scopes set otherwise False.
251 """
252 return True if not self._scopes else False
253
254 @_helpers.copy_docstring(credentials.Scoped)
255 def with_scopes(self, scopes):
Christophe Tatonb649b432018-02-08 14:12:23 -0800256 return self.__class__(
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700257 self._signer,
258 service_account_email=self._service_account_email,
259 scopes=scopes,
260 token_uri=self._token_uri,
261 subject=self._subject,
Hiranya Jayathilaka6a3f0ec2017-08-10 09:11:02 -0700262 project_id=self._project_id,
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700263 quota_project_id=self._quota_project_id,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700264 additional_claims=self._additional_claims.copy(),
265 )
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700266
267 def with_subject(self, subject):
268 """Create a copy of these credentials with the specified subject.
269
270 Args:
271 subject (str): The subject claim.
272
273 Returns:
274 google.auth.service_account.Credentials: A new credentials
275 instance.
276 """
Christophe Tatonb649b432018-02-08 14:12:23 -0800277 return self.__class__(
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700278 self._signer,
279 service_account_email=self._service_account_email,
280 scopes=self._scopes,
281 token_uri=self._token_uri,
282 subject=subject,
Hiranya Jayathilaka6a3f0ec2017-08-10 09:11:02 -0700283 project_id=self._project_id,
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700284 quota_project_id=self._quota_project_id,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700285 additional_claims=self._additional_claims.copy(),
286 )
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700287
Jon Wayne Parrott75c78b22017-03-23 13:14:53 -0700288 def with_claims(self, additional_claims):
289 """Returns a copy of these credentials with modified claims.
290
291 Args:
292 additional_claims (Mapping[str, str]): Any additional claims for
293 the JWT payload. This will be merged with the current
294 additional claims.
295
296 Returns:
297 google.auth.service_account.Credentials: A new credentials
298 instance.
299 """
300 new_additional_claims = copy.deepcopy(self._additional_claims)
301 new_additional_claims.update(additional_claims or {})
302
Christophe Tatonb649b432018-02-08 14:12:23 -0800303 return self.__class__(
Jon Wayne Parrott75c78b22017-03-23 13:14:53 -0700304 self._signer,
305 service_account_email=self._service_account_email,
306 scopes=self._scopes,
307 token_uri=self._token_uri,
308 subject=self._subject,
Hiranya Jayathilaka6a3f0ec2017-08-10 09:11:02 -0700309 project_id=self._project_id,
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700310 quota_project_id=self._quota_project_id,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700311 additional_claims=new_additional_claims,
312 )
Jon Wayne Parrott75c78b22017-03-23 13:14:53 -0700313
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700314 def with_quota_project(self, quota_project_id):
315 """Returns a copy of these credentials with a modified quota project.
316
317 Args:
318 quota_project_id (str): The project to use for quota and
319 billing purposes
320
321 Returns:
322 google.auth.service_account.Credentials: A new credentials
323 instance.
324 """
325 return self.__class__(
326 self._signer,
327 service_account_email=self._service_account_email,
328 scopes=self._scopes,
329 token_uri=self._token_uri,
330 subject=self._subject,
331 project_id=self._project_id,
332 quota_project_id=quota_project_id,
333 additional_claims=self._additional_claims.copy(),
334 )
335
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700336 def _make_authorization_grant_assertion(self):
337 """Create the OAuth 2.0 assertion.
338
339 This assertion is used during the OAuth 2.0 grant to acquire an
340 access token.
341
342 Returns:
343 bytes: The authorization grant assertion.
344 """
345 now = _helpers.utcnow()
346 lifetime = datetime.timedelta(seconds=_DEFAULT_TOKEN_LIFETIME_SECS)
347 expiry = now + lifetime
348
349 payload = {
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700350 "iat": _helpers.datetime_to_secs(now),
351 "exp": _helpers.datetime_to_secs(expiry),
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700352 # The issuer must be the service account email.
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700353 "iss": self._service_account_email,
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700354 # The audience must be the auth token endpoint's URI
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700355 "aud": self._token_uri,
356 "scope": _helpers.scopes_to_string(self._scopes or ()),
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700357 }
358
359 payload.update(self._additional_claims)
360
361 # The subject can be a user email for domain-wide delegation.
362 if self._subject:
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700363 payload.setdefault("sub", self._subject)
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700364
365 token = jwt.encode(self._signer, payload)
366
367 return token
368
369 @_helpers.copy_docstring(credentials.Credentials)
370 def refresh(self, request):
371 assertion = self._make_authorization_grant_assertion()
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700372 access_token, expiry, _ = _client.jwt_grant(request, self._token_uri, assertion)
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700373 self.token = access_token
374 self.expiry = expiry
375
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700376 @_helpers.copy_docstring(credentials.Credentials)
377 def apply(self, headers, token=None):
378 super(Credentials, self).apply(headers, token=token)
379 if self.quota_project_id is not None:
380 headers["x-goog-user-project"] = self.quota_project_id
381
Jon Wayne Parrottab9eba32016-10-17 10:49:57 -0700382 @_helpers.copy_docstring(credentials.Signing)
383 def sign_bytes(self, message):
384 return self._signer.sign(message)
Jon Wayne Parrott4c883f02016-12-02 14:26:33 -0800385
386 @property
387 @_helpers.copy_docstring(credentials.Signing)
Jon Wayne Parrottd7221672017-02-16 09:05:11 -0800388 def signer(self):
389 return self._signer
390
391 @property
392 @_helpers.copy_docstring(credentials.Signing)
Jon Wayne Parrott4c883f02016-12-02 14:26:33 -0800393 def signer_email(self):
394 return self._service_account_email
Christophe Tatonb649b432018-02-08 14:12:23 -0800395
396
397class IDTokenCredentials(credentials.Signing, credentials.Credentials):
398 """Open ID Connect ID Token-based service account credentials.
399
400 These credentials are largely similar to :class:`.Credentials`, but instead
401 of using an OAuth 2.0 Access Token as the bearer token, they use an Open
402 ID Connect ID Token as the bearer token. These credentials are useful when
403 communicating to services that require ID Tokens and can not accept access
404 tokens.
405
406 Usually, you'll create these credentials with one of the helper
407 constructors. To create credentials using a Google service account
408 private key JSON file::
409
410 credentials = (
411 service_account.IDTokenCredentials.from_service_account_file(
412 'service-account.json'))
413
414 Or if you already have the service account file loaded::
415
416 service_account_info = json.load(open('service_account.json'))
417 credentials = (
418 service_account.IDTokenCredentials.from_service_account_info(
419 service_account_info))
420
421 Both helper methods pass on arguments to the constructor, so you can
422 specify additional scopes and a subject if necessary::
423
424 credentials = (
425 service_account.IDTokenCredentials.from_service_account_file(
426 'service-account.json',
427 scopes=['email'],
428 subject='user@example.com'))
429`
430 The credentials are considered immutable. If you want to modify the scopes
431 or the subject used for delegation, use :meth:`with_scopes` or
432 :meth:`with_subject`::
433
434 scoped_credentials = credentials.with_scopes(['email'])
435 delegated_credentials = credentials.with_subject(subject)
436
437 """
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700438
439 def __init__(
440 self,
441 signer,
442 service_account_email,
443 token_uri,
444 target_audience,
445 additional_claims=None,
446 ):
Christophe Tatonb649b432018-02-08 14:12:23 -0800447 """
448 Args:
449 signer (google.auth.crypt.Signer): The signer used to sign JWTs.
450 service_account_email (str): The service account's email.
451 token_uri (str): The OAuth 2.0 Token URI.
452 target_audience (str): The intended audience for these credentials,
453 used when requesting the ID Token. The ID Token's ``aud`` claim
454 will be set to this string.
455 additional_claims (Mapping[str, str]): Any additional claims for
456 the JWT assertion used in the authorization grant.
457
458 .. note:: Typically one of the helper constructors
459 :meth:`from_service_account_file` or
460 :meth:`from_service_account_info` are used instead of calling the
461 constructor directly.
462 """
463 super(IDTokenCredentials, self).__init__()
464 self._signer = signer
465 self._service_account_email = service_account_email
466 self._token_uri = token_uri
467 self._target_audience = target_audience
468
469 if additional_claims is not None:
470 self._additional_claims = additional_claims
471 else:
472 self._additional_claims = {}
473
474 @classmethod
475 def _from_signer_and_info(cls, signer, info, **kwargs):
476 """Creates a credentials instance from a signer and service account
477 info.
478
479 Args:
480 signer (google.auth.crypt.Signer): The signer used to sign JWTs.
481 info (Mapping[str, str]): The service account info.
482 kwargs: Additional arguments to pass to the constructor.
483
484 Returns:
485 google.auth.jwt.IDTokenCredentials: The constructed credentials.
486
487 Raises:
488 ValueError: If the info is not in the expected format.
489 """
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700490 kwargs.setdefault("service_account_email", info["client_email"])
491 kwargs.setdefault("token_uri", info["token_uri"])
Christophe Tatonb649b432018-02-08 14:12:23 -0800492 return cls(signer, **kwargs)
493
494 @classmethod
495 def from_service_account_info(cls, info, **kwargs):
496 """Creates a credentials instance from parsed service account info.
497
498 Args:
499 info (Mapping[str, str]): The service account info in Google
500 format.
501 kwargs: Additional arguments to pass to the constructor.
502
503 Returns:
504 google.auth.service_account.IDTokenCredentials: The constructed
505 credentials.
506
507 Raises:
508 ValueError: If the info is not in the expected format.
509 """
510 signer = _service_account_info.from_dict(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700511 info, require=["client_email", "token_uri"]
512 )
Christophe Tatonb649b432018-02-08 14:12:23 -0800513 return cls._from_signer_and_info(signer, info, **kwargs)
514
515 @classmethod
516 def from_service_account_file(cls, filename, **kwargs):
517 """Creates a credentials instance from a service account json file.
518
519 Args:
520 filename (str): The path to the service account json file.
521 kwargs: Additional arguments to pass to the constructor.
522
523 Returns:
524 google.auth.service_account.IDTokenCredentials: The constructed
525 credentials.
526 """
527 info, signer = _service_account_info.from_filename(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700528 filename, require=["client_email", "token_uri"]
529 )
Christophe Tatonb649b432018-02-08 14:12:23 -0800530 return cls._from_signer_and_info(signer, info, **kwargs)
531
532 def with_target_audience(self, target_audience):
533 """Create a copy of these credentials with the specified target
534 audience.
535
536 Args:
537 target_audience (str): The intended audience for these credentials,
538 used when requesting the ID Token.
539
540 Returns:
541 google.auth.service_account.IDTokenCredentials: A new credentials
542 instance.
543 """
544 return self.__class__(
545 self._signer,
546 service_account_email=self._service_account_email,
547 token_uri=self._token_uri,
548 target_audience=target_audience,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700549 additional_claims=self._additional_claims.copy(),
550 )
Christophe Tatonb649b432018-02-08 14:12:23 -0800551
552 def _make_authorization_grant_assertion(self):
553 """Create the OAuth 2.0 assertion.
554
555 This assertion is used during the OAuth 2.0 grant to acquire an
556 ID token.
557
558 Returns:
559 bytes: The authorization grant assertion.
560 """
561 now = _helpers.utcnow()
562 lifetime = datetime.timedelta(seconds=_DEFAULT_TOKEN_LIFETIME_SECS)
563 expiry = now + lifetime
564
565 payload = {
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700566 "iat": _helpers.datetime_to_secs(now),
567 "exp": _helpers.datetime_to_secs(expiry),
Christophe Tatonb649b432018-02-08 14:12:23 -0800568 # The issuer must be the service account email.
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700569 "iss": self.service_account_email,
Christophe Tatonb649b432018-02-08 14:12:23 -0800570 # The audience must be the auth token endpoint's URI
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700571 "aud": self._token_uri,
Christophe Tatonb649b432018-02-08 14:12:23 -0800572 # The target audience specifies which service the ID token is
573 # intended for.
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700574 "target_audience": self._target_audience,
Christophe Tatonb649b432018-02-08 14:12:23 -0800575 }
576
577 payload.update(self._additional_claims)
578
579 token = jwt.encode(self._signer, payload)
580
581 return token
582
583 @_helpers.copy_docstring(credentials.Credentials)
584 def refresh(self, request):
585 assertion = self._make_authorization_grant_assertion()
586 access_token, expiry, _ = _client.id_token_jwt_grant(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700587 request, self._token_uri, assertion
588 )
Christophe Tatonb649b432018-02-08 14:12:23 -0800589 self.token = access_token
590 self.expiry = expiry
591
592 @property
593 def service_account_email(self):
594 """The service account email."""
595 return self._service_account_email
596
597 @_helpers.copy_docstring(credentials.Signing)
598 def sign_bytes(self, message):
599 return self._signer.sign(message)
600
601 @property
602 @_helpers.copy_docstring(credentials.Signing)
603 def signer(self):
604 return self._signer
605
606 @property
607 @_helpers.copy_docstring(credentials.Signing)
608 def signer_email(self):
609 return self._service_account_email