We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Invalid type for expiry when using GCE metadata server
#### Environment details

  - OS: Linux
  - Python version: 3.8.2
  - pip version: 20.0.2
  - `google-auth` version: 1.12.0

#### Steps to reproduce

  1. Create an ID token using the GCE metadata server:
      ```python
      from google.auth import compute_engine
      import google.auth.transport.requests
      request = google.auth.transport.requests.Request()
      target_audience = 'https://example.com'
      creds = compute_engine.IDTokenCredentials(request, target_audience, use_metadata_identity_endpoint=True)
      ```
  2. Try to use the credentials to authorize a request:
      ```python
      from google.auth.transport.requests import AuthorizedSession
      session = AuthorizedSession(credentials)
      response = session.get('https://example.com')
      ```

This results in an error:
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.8/site-packages/google/auth/credentials.py", line 66, in expired
    skewed_expiry = self.expiry - _helpers.CLOCK_SKEW
TypeError: unsupported operand type(s) for -: 'int' and 'datetime.timedelta'
```

I think the issue is on [this line](https://github.com/googleapis/google-auth-library-python/blob/master/google/auth/compute_engine/credentials.py#L294). `payload["exp"]` should (apparently) be getting parsed into a `datetime.timedelta`

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `google/auth/compute_engine/credentials.py`
Content:
```
1 # Copyright 2016 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 """Google Compute Engine credentials.
16 
17 This module provides authentication for application running on Google Compute
18 Engine using the Compute Engine metadata server.
19 
20 """
21 
22 import datetime
23 
24 import six
25 
26 from google.auth import _helpers
27 from google.auth import credentials
28 from google.auth import exceptions
29 from google.auth import iam
30 from google.auth import jwt
31 from google.auth.compute_engine import _metadata
32 from google.oauth2 import _client
33 
34 
35 class Credentials(credentials.ReadOnlyScoped, credentials.Credentials):
36     """Compute Engine Credentials.
37 
38     These credentials use the Google Compute Engine metadata server to obtain
39     OAuth 2.0 access tokens associated with the instance's service account.
40 
41     For more information about Compute Engine authentication, including how
42     to configure scopes, see the `Compute Engine authentication
43     documentation`_.
44 
45     .. note:: Compute Engine instances can be created with scopes and therefore
46         these credentials are considered to be 'scoped'. However, you can
47         not use :meth:`~google.auth.credentials.ScopedCredentials.with_scopes`
48         because it is not possible to change the scopes that the instance
49         has. Also note that
50         :meth:`~google.auth.credentials.ScopedCredentials.has_scopes` will not
51         work until the credentials have been refreshed.
52 
53     .. _Compute Engine authentication documentation:
54         https://cloud.google.com/compute/docs/authentication#using
55     """
56 
57     def __init__(self, service_account_email="default"):
58         """
59         Args:
60             service_account_email (str): The service account email to use, or
61                 'default'. A Compute Engine instance may have multiple service
62                 accounts.
63         """
64         super(Credentials, self).__init__()
65         self._service_account_email = service_account_email
66 
67     def _retrieve_info(self, request):
68         """Retrieve information about the service account.
69 
70         Updates the scopes and retrieves the full service account email.
71 
72         Args:
73             request (google.auth.transport.Request): The object used to make
74                 HTTP requests.
75         """
76         info = _metadata.get_service_account_info(
77             request, service_account=self._service_account_email
78         )
79 
80         self._service_account_email = info["email"]
81         self._scopes = info["scopes"]
82 
83     def refresh(self, request):
84         """Refresh the access token and scopes.
85 
86         Args:
87             request (google.auth.transport.Request): The object used to make
88                 HTTP requests.
89 
90         Raises:
91             google.auth.exceptions.RefreshError: If the Compute Engine metadata
92                 service can't be reached if if the instance has not
93                 credentials.
94         """
95         try:
96             self._retrieve_info(request)
97             self.token, self.expiry = _metadata.get_service_account_token(
98                 request, service_account=self._service_account_email
99             )
100         except exceptions.TransportError as caught_exc:
101             new_exc = exceptions.RefreshError(caught_exc)
102             six.raise_from(new_exc, caught_exc)
103 
104     @property
105     def service_account_email(self):
106         """The service account email.
107 
108         .. note:: This is not guaranteed to be set until :meth:`refresh` has been
109             called.
110         """
111         return self._service_account_email
112 
113     @property
114     def requires_scopes(self):
115         """False: Compute Engine credentials can not be scoped."""
116         return False
117 
118 
119 _DEFAULT_TOKEN_LIFETIME_SECS = 3600  # 1 hour in seconds
120 _DEFAULT_TOKEN_URI = "https://www.googleapis.com/oauth2/v4/token"
121 
122 
123 class IDTokenCredentials(credentials.Credentials, credentials.Signing):
124     """Open ID Connect ID Token-based service account credentials.
125 
126     These credentials relies on the default service account of a GCE instance.
127 
128     ID token can be requested from `GCE metadata server identity endpoint`_, IAM
129     token endpoint or other token endpoints you specify. If metadata server
130     identity endpoint is not used, the GCE instance must have been started with
131     a service account that has access to the IAM Cloud API.
132 
133     .. _GCE metadata server identity endpoint:
134         https://cloud.google.com/compute/docs/instances/verifying-instance-identity
135     """
136 
137     def __init__(
138         self,
139         request,
140         target_audience,
141         token_uri=None,
142         additional_claims=None,
143         service_account_email=None,
144         signer=None,
145         use_metadata_identity_endpoint=False,
146     ):
147         """
148         Args:
149             request (google.auth.transport.Request): The object used to make
150                 HTTP requests.
151             target_audience (str): The intended audience for these credentials,
152                 used when requesting the ID Token. The ID Token's ``aud`` claim
153                 will be set to this string.
154             token_uri (str): The OAuth 2.0 Token URI.
155             additional_claims (Mapping[str, str]): Any additional claims for
156                 the JWT assertion used in the authorization grant.
157             service_account_email (str): Optional explicit service account to
158                 use to sign JWT tokens.
159                 By default, this is the default GCE service account.
160             signer (google.auth.crypt.Signer): The signer used to sign JWTs.
161                 In case the signer is specified, the request argument will be
162                 ignored.
163             use_metadata_identity_endpoint (bool): Whether to use GCE metadata
164                 identity endpoint. For backward compatibility the default value
165                 is False. If set to True, ``token_uri``, ``additional_claims``,
166                 ``service_account_email``, ``signer`` argument should not be set;
167                 otherwise ValueError will be raised.
168 
169         Raises:
170             ValueError:
171                 If ``use_metadata_identity_endpoint`` is set to True, and one of
172                 ``token_uri``, ``additional_claims``, ``service_account_email``,
173                  ``signer`` arguments is set.
174         """
175         super(IDTokenCredentials, self).__init__()
176 
177         self._use_metadata_identity_endpoint = use_metadata_identity_endpoint
178         self._target_audience = target_audience
179 
180         if use_metadata_identity_endpoint:
181             if token_uri or additional_claims or service_account_email or signer:
182                 raise ValueError(
183                     "If use_metadata_identity_endpoint is set, token_uri, "
184                     "additional_claims, service_account_email, signer arguments"
185                     " must not be set"
186                 )
187             self._token_uri = None
188             self._additional_claims = None
189             self._signer = None
190 
191         if service_account_email is None:
192             sa_info = _metadata.get_service_account_info(request)
193             self._service_account_email = sa_info["email"]
194         else:
195             self._service_account_email = service_account_email
196 
197         if not use_metadata_identity_endpoint:
198             if signer is None:
199                 signer = iam.Signer(
200                     request=request,
201                     credentials=Credentials(),
202                     service_account_email=self._service_account_email,
203                 )
204             self._signer = signer
205             self._token_uri = token_uri or _DEFAULT_TOKEN_URI
206 
207             if additional_claims is not None:
208                 self._additional_claims = additional_claims
209             else:
210                 self._additional_claims = {}
211 
212     def with_target_audience(self, target_audience):
213         """Create a copy of these credentials with the specified target
214         audience.
215         Args:
216             target_audience (str): The intended audience for these credentials,
217             used when requesting the ID Token.
218         Returns:
219             google.auth.service_account.IDTokenCredentials: A new credentials
220                 instance.
221         """
222         # since the signer is already instantiated,
223         # the request is not needed
224         if self._use_metadata_identity_endpoint:
225             return self.__class__(
226                 None,
227                 target_audience=target_audience,
228                 use_metadata_identity_endpoint=True,
229             )
230         else:
231             return self.__class__(
232                 None,
233                 service_account_email=self._service_account_email,
234                 token_uri=self._token_uri,
235                 target_audience=target_audience,
236                 additional_claims=self._additional_claims.copy(),
237                 signer=self.signer,
238                 use_metadata_identity_endpoint=False,
239             )
240 
241     def _make_authorization_grant_assertion(self):
242         """Create the OAuth 2.0 assertion.
243         This assertion is used during the OAuth 2.0 grant to acquire an
244         ID token.
245         Returns:
246             bytes: The authorization grant assertion.
247         """
248         now = _helpers.utcnow()
249         lifetime = datetime.timedelta(seconds=_DEFAULT_TOKEN_LIFETIME_SECS)
250         expiry = now + lifetime
251 
252         payload = {
253             "iat": _helpers.datetime_to_secs(now),
254             "exp": _helpers.datetime_to_secs(expiry),
255             # The issuer must be the service account email.
256             "iss": self.service_account_email,
257             # The audience must be the auth token endpoint's URI
258             "aud": self._token_uri,
259             # The target audience specifies which service the ID token is
260             # intended for.
261             "target_audience": self._target_audience,
262         }
263 
264         payload.update(self._additional_claims)
265 
266         token = jwt.encode(self._signer, payload)
267 
268         return token
269 
270     def _call_metadata_identity_endpoint(self, request):
271         """Request ID token from metadata identity endpoint.
272 
273         Args:
274             request (google.auth.transport.Request): The object used to make
275                 HTTP requests.
276 
277         Raises:
278             google.auth.exceptions.RefreshError: If the Compute Engine metadata
279                 service can't be reached or if the instance has no credentials.
280             ValueError: If extracting expiry from the obtained ID token fails.
281         """
282         try:
283             id_token = _metadata.get(
284                 request,
285                 "instance/service-accounts/default/identity?audience={}&format=full".format(
286                     self._target_audience
287                 ),
288             )
289         except exceptions.TransportError as caught_exc:
290             new_exc = exceptions.RefreshError(caught_exc)
291             six.raise_from(new_exc, caught_exc)
292 
293         _, payload, _, _ = jwt._unverified_decode(id_token)
294         return id_token, payload["exp"]
295 
296     def refresh(self, request):
297         """Refreshes the ID token.
298 
299         Args:
300             request (google.auth.transport.Request): The object used to make
301                 HTTP requests.
302 
303         Raises:
304             google.auth.exceptions.RefreshError: If the credentials could
305                 not be refreshed.
306             ValueError: If extracting expiry from the obtained ID token fails.
307         """
308         if self._use_metadata_identity_endpoint:
309             self.token, self.expiry = self._call_metadata_identity_endpoint(request)
310         else:
311             assertion = self._make_authorization_grant_assertion()
312             access_token, expiry, _ = _client.id_token_jwt_grant(
313                 request, self._token_uri, assertion
314             )
315             self.token = access_token
316             self.expiry = expiry
317 
318     @property
319     @_helpers.copy_docstring(credentials.Signing)
320     def signer(self):
321         return self._signer
322 
323     def sign_bytes(self, message):
324         """Signs the given message.
325 
326         Args:
327             message (bytes): The message to sign.
328 
329         Returns:
330             bytes: The message's cryptographic signature.
331 
332         Raises:
333             ValueError:
334                 Signer is not available if metadata identity endpoint is used.
335         """
336         if self._use_metadata_identity_endpoint:
337             raise ValueError(
338                 "Signer is not available if metadata identity endpoint is used"
339             )
340         return self._signer.sign(message)
341 
342     @property
343     def service_account_email(self):
344         """The service account email."""
345         return self._service_account_email
346 
347     @property
348     def signer_email(self):
349         return self._service_account_email
350
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/google/auth/compute_engine/credentials.py b/google/auth/compute_engine/credentials.py
--- a/google/auth/compute_engine/credentials.py
+++ b/google/auth/compute_engine/credentials.py
@@ -274,6 +274,9 @@
             request (google.auth.transport.Request): The object used to make
                 HTTP requests.
 
+        Returns:
+            Tuple[str, datetime.datetime]: The ID token and the expiry of the ID token.
+
         Raises:
             google.auth.exceptions.RefreshError: If the Compute Engine metadata
                 service can't be reached or if the instance has no credentials.
@@ -291,7 +294,7 @@
             six.raise_from(new_exc, caught_exc)
 
         _, payload, _, _ = jwt._unverified_decode(id_token)
-        return id_token, payload["exp"]
+        return id_token, datetime.datetime.fromtimestamp(payload["exp"])
 
     def refresh(self, request):
         """Refreshes the ID token.

{"golden_diff": "diff --git a/google/auth/compute_engine/credentials.py b/google/auth/compute_engine/credentials.py\n--- a/google/auth/compute_engine/credentials.py\n+++ b/google/auth/compute_engine/credentials.py\n@@ -274,6 +274,9 @@\n             request (google.auth.transport.Request): The object used to make\n                 HTTP requests.\n \n+        Returns:\n+            Tuple[str, datetime.datetime]: The ID token and the expiry of the ID token.\n+\n         Raises:\n             google.auth.exceptions.RefreshError: If the Compute Engine metadata\n                 service can't be reached or if the instance has no credentials.\n@@ -291,7 +294,7 @@\n             six.raise_from(new_exc, caught_exc)\n \n         _, payload, _, _ = jwt._unverified_decode(id_token)\n-        return id_token, payload[\"exp\"]\n+        return id_token, datetime.datetime.fromtimestamp(payload[\"exp\"])\n \n     def refresh(self, request):\n         \"\"\"Refreshes the ID token.\n", "issue": "Invalid type for expiry when using GCE metadata server\n#### Environment details\r\n\r\n  - OS: Linux\r\n  - Python version: 3.8.2\r\n  - pip version: 20.0.2\r\n  - `google-auth` version: 1.12.0\r\n\r\n#### Steps to reproduce\r\n\r\n  1. Create an ID token using the GCE metadata server:\r\n      ```python\r\n      from google.auth import compute_engine\r\n      import google.auth.transport.requests\r\n      request = google.auth.transport.requests.Request()\r\n      target_audience = 'https://example.com'\r\n      creds = compute_engine.IDTokenCredentials(request, target_audience, use_metadata_identity_endpoint=True)\r\n      ```\r\n  2. Try to use the credentials to authorize a request:\r\n      ```python\r\n      from google.auth.transport.requests import AuthorizedSession\r\n      session = AuthorizedSession(credentials)\r\n      response = session.get('https://example.com')\r\n      ```\r\n\r\nThis results in an error:\r\n```\r\nTraceback (most recent call last):\r\n  File \"<stdin>\", line 1, in <module>\r\n  File \"/usr/local/lib/python3.8/site-packages/google/auth/credentials.py\", line 66, in expired\r\n    skewed_expiry = self.expiry - _helpers.CLOCK_SKEW\r\nTypeError: unsupported operand type(s) for -: 'int' and 'datetime.timedelta'\r\n```\r\n\r\nI think the issue is on [this line](https://github.com/googleapis/google-auth-library-python/blob/master/google/auth/compute_engine/credentials.py#L294). `payload[\"exp\"]` should (apparently) be getting parsed into a `datetime.timedelta`\n", "before_files": [{"content": "# Copyright 2016 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Google Compute Engine credentials.\n\nThis module provides authentication for application running on Google Compute\nEngine using the Compute Engine metadata server.\n\n\"\"\"\n\nimport datetime\n\nimport six\n\nfrom google.auth import _helpers\nfrom google.auth import credentials\nfrom google.auth import exceptions\nfrom google.auth import iam\nfrom google.auth import jwt\nfrom google.auth.compute_engine import _metadata\nfrom google.oauth2 import _client\n\n\nclass Credentials(credentials.ReadOnlyScoped, credentials.Credentials):\n    \"\"\"Compute Engine Credentials.\n\n    These credentials use the Google Compute Engine metadata server to obtain\n    OAuth 2.0 access tokens associated with the instance's service account.\n\n    For more information about Compute Engine authentication, including how\n    to configure scopes, see the `Compute Engine authentication\n    documentation`_.\n\n    .. note:: Compute Engine instances can be created with scopes and therefore\n        these credentials are considered to be 'scoped'. However, you can\n        not use :meth:`~google.auth.credentials.ScopedCredentials.with_scopes`\n        because it is not possible to change the scopes that the instance\n        has. Also note that\n        :meth:`~google.auth.credentials.ScopedCredentials.has_scopes` will not\n        work until the credentials have been refreshed.\n\n    .. _Compute Engine authentication documentation:\n        https://cloud.google.com/compute/docs/authentication#using\n    \"\"\"\n\n    def __init__(self, service_account_email=\"default\"):\n        \"\"\"\n        Args:\n            service_account_email (str): The service account email to use, or\n                'default'. A Compute Engine instance may have multiple service\n                accounts.\n        \"\"\"\n        super(Credentials, self).__init__()\n        self._service_account_email = service_account_email\n\n    def _retrieve_info(self, request):\n        \"\"\"Retrieve information about the service account.\n\n        Updates the scopes and retrieves the full service account email.\n\n        Args:\n            request (google.auth.transport.Request): The object used to make\n                HTTP requests.\n        \"\"\"\n        info = _metadata.get_service_account_info(\n            request, service_account=self._service_account_email\n        )\n\n        self._service_account_email = info[\"email\"]\n        self._scopes = info[\"scopes\"]\n\n    def refresh(self, request):\n        \"\"\"Refresh the access token and scopes.\n\n        Args:\n            request (google.auth.transport.Request): The object used to make\n                HTTP requests.\n\n        Raises:\n            google.auth.exceptions.RefreshError: If the Compute Engine metadata\n                service can't be reached if if the instance has not\n                credentials.\n        \"\"\"\n        try:\n            self._retrieve_info(request)\n            self.token, self.expiry = _metadata.get_service_account_token(\n                request, service_account=self._service_account_email\n            )\n        except exceptions.TransportError as caught_exc:\n            new_exc = exceptions.RefreshError(caught_exc)\n            six.raise_from(new_exc, caught_exc)\n\n    @property\n    def service_account_email(self):\n        \"\"\"The service account email.\n\n        .. note:: This is not guaranteed to be set until :meth:`refresh` has been\n            called.\n        \"\"\"\n        return self._service_account_email\n\n    @property\n    def requires_scopes(self):\n        \"\"\"False: Compute Engine credentials can not be scoped.\"\"\"\n        return False\n\n\n_DEFAULT_TOKEN_LIFETIME_SECS = 3600  # 1 hour in seconds\n_DEFAULT_TOKEN_URI = \"https://www.googleapis.com/oauth2/v4/token\"\n\n\nclass IDTokenCredentials(credentials.Credentials, credentials.Signing):\n    \"\"\"Open ID Connect ID Token-based service account credentials.\n\n    These credentials relies on the default service account of a GCE instance.\n\n    ID token can be requested from `GCE metadata server identity endpoint`_, IAM\n    token endpoint or other token endpoints you specify. If metadata server\n    identity endpoint is not used, the GCE instance must have been started with\n    a service account that has access to the IAM Cloud API.\n\n    .. _GCE metadata server identity endpoint:\n        https://cloud.google.com/compute/docs/instances/verifying-instance-identity\n    \"\"\"\n\n    def __init__(\n        self,\n        request,\n        target_audience,\n        token_uri=None,\n        additional_claims=None,\n        service_account_email=None,\n        signer=None,\n        use_metadata_identity_endpoint=False,\n    ):\n        \"\"\"\n        Args:\n            request (google.auth.transport.Request): The object used to make\n                HTTP requests.\n            target_audience (str): The intended audience for these credentials,\n                used when requesting the ID Token. The ID Token's ``aud`` claim\n                will be set to this string.\n            token_uri (str): The OAuth 2.0 Token URI.\n            additional_claims (Mapping[str, str]): Any additional claims for\n                the JWT assertion used in the authorization grant.\n            service_account_email (str): Optional explicit service account to\n                use to sign JWT tokens.\n                By default, this is the default GCE service account.\n            signer (google.auth.crypt.Signer): The signer used to sign JWTs.\n                In case the signer is specified, the request argument will be\n                ignored.\n            use_metadata_identity_endpoint (bool): Whether to use GCE metadata\n                identity endpoint. For backward compatibility the default value\n                is False. If set to True, ``token_uri``, ``additional_claims``,\n                ``service_account_email``, ``signer`` argument should not be set;\n                otherwise ValueError will be raised.\n\n        Raises:\n            ValueError:\n                If ``use_metadata_identity_endpoint`` is set to True, and one of\n                ``token_uri``, ``additional_claims``, ``service_account_email``,\n                 ``signer`` arguments is set.\n        \"\"\"\n        super(IDTokenCredentials, self).__init__()\n\n        self._use_metadata_identity_endpoint = use_metadata_identity_endpoint\n        self._target_audience = target_audience\n\n        if use_metadata_identity_endpoint:\n            if token_uri or additional_claims or service_account_email or signer:\n                raise ValueError(\n                    \"If use_metadata_identity_endpoint is set, token_uri, \"\n                    \"additional_claims, service_account_email, signer arguments\"\n                    \" must not be set\"\n                )\n            self._token_uri = None\n            self._additional_claims = None\n            self._signer = None\n\n        if service_account_email is None:\n            sa_info = _metadata.get_service_account_info(request)\n            self._service_account_email = sa_info[\"email\"]\n        else:\n            self._service_account_email = service_account_email\n\n        if not use_metadata_identity_endpoint:\n            if signer is None:\n                signer = iam.Signer(\n                    request=request,\n                    credentials=Credentials(),\n                    service_account_email=self._service_account_email,\n                )\n            self._signer = signer\n            self._token_uri = token_uri or _DEFAULT_TOKEN_URI\n\n            if additional_claims is not None:\n                self._additional_claims = additional_claims\n            else:\n                self._additional_claims = {}\n\n    def with_target_audience(self, target_audience):\n        \"\"\"Create a copy of these credentials with the specified target\n        audience.\n        Args:\n            target_audience (str): The intended audience for these credentials,\n            used when requesting the ID Token.\n        Returns:\n            google.auth.service_account.IDTokenCredentials: A new credentials\n                instance.\n        \"\"\"\n        # since the signer is already instantiated,\n        # the request is not needed\n        if self._use_metadata_identity_endpoint:\n            return self.__class__(\n                None,\n                target_audience=target_audience,\n                use_metadata_identity_endpoint=True,\n            )\n        else:\n            return self.__class__(\n                None,\n                service_account_email=self._service_account_email,\n                token_uri=self._token_uri,\n                target_audience=target_audience,\n                additional_claims=self._additional_claims.copy(),\n                signer=self.signer,\n                use_metadata_identity_endpoint=False,\n            )\n\n    def _make_authorization_grant_assertion(self):\n        \"\"\"Create the OAuth 2.0 assertion.\n        This assertion is used during the OAuth 2.0 grant to acquire an\n        ID token.\n        Returns:\n            bytes: The authorization grant assertion.\n        \"\"\"\n        now = _helpers.utcnow()\n        lifetime = datetime.timedelta(seconds=_DEFAULT_TOKEN_LIFETIME_SECS)\n        expiry = now + lifetime\n\n        payload = {\n            \"iat\": _helpers.datetime_to_secs(now),\n            \"exp\": _helpers.datetime_to_secs(expiry),\n            # The issuer must be the service account email.\n            \"iss\": self.service_account_email,\n            # The audience must be the auth token endpoint's URI\n            \"aud\": self._token_uri,\n            # The target audience specifies which service the ID token is\n            # intended for.\n            \"target_audience\": self._target_audience,\n        }\n\n        payload.update(self._additional_claims)\n\n        token = jwt.encode(self._signer, payload)\n\n        return token\n\n    def _call_metadata_identity_endpoint(self, request):\n        \"\"\"Request ID token from metadata identity endpoint.\n\n        Args:\n            request (google.auth.transport.Request): The object used to make\n                HTTP requests.\n\n        Raises:\n            google.auth.exceptions.RefreshError: If the Compute Engine metadata\n                service can't be reached or if the instance has no credentials.\n            ValueError: If extracting expiry from the obtained ID token fails.\n        \"\"\"\n        try:\n            id_token = _metadata.get(\n                request,\n                \"instance/service-accounts/default/identity?audience={}&format=full\".format(\n                    self._target_audience\n                ),\n            )\n        except exceptions.TransportError as caught_exc:\n            new_exc = exceptions.RefreshError(caught_exc)\n            six.raise_from(new_exc, caught_exc)\n\n        _, payload, _, _ = jwt._unverified_decode(id_token)\n        return id_token, payload[\"exp\"]\n\n    def refresh(self, request):\n        \"\"\"Refreshes the ID token.\n\n        Args:\n            request (google.auth.transport.Request): The object used to make\n                HTTP requests.\n\n        Raises:\n            google.auth.exceptions.RefreshError: If the credentials could\n                not be refreshed.\n            ValueError: If extracting expiry from the obtained ID token fails.\n        \"\"\"\n        if self._use_metadata_identity_endpoint:\n            self.token, self.expiry = self._call_metadata_identity_endpoint(request)\n        else:\n            assertion = self._make_authorization_grant_assertion()\n            access_token, expiry, _ = _client.id_token_jwt_grant(\n                request, self._token_uri, assertion\n            )\n            self.token = access_token\n            self.expiry = expiry\n\n    @property\n    @_helpers.copy_docstring(credentials.Signing)\n    def signer(self):\n        return self._signer\n\n    def sign_bytes(self, message):\n        \"\"\"Signs the given message.\n\n        Args:\n            message (bytes): The message to sign.\n\n        Returns:\n            bytes: The message's cryptographic signature.\n\n        Raises:\n            ValueError:\n                Signer is not available if metadata identity endpoint is used.\n        \"\"\"\n        if self._use_metadata_identity_endpoint:\n            raise ValueError(\n                \"Signer is not available if metadata identity endpoint is used\"\n            )\n        return self._signer.sign(message)\n\n    @property\n    def service_account_email(self):\n        \"\"\"The service account email.\"\"\"\n        return self._service_account_email\n\n    @property\n    def signer_email(self):\n        return self._service_account_email\n", "path": "google/auth/compute_engine/credentials.py"}], "after_files": [{"content": "# Copyright 2016 Google LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Google Compute Engine credentials.\n\nThis module provides authentication for application running on Google Compute\nEngine using the Compute Engine metadata server.\n\n\"\"\"\n\nimport datetime\n\nimport six\n\nfrom google.auth import _helpers\nfrom google.auth import credentials\nfrom google.auth import exceptions\nfrom google.auth import iam\nfrom google.auth import jwt\nfrom google.auth.compute_engine import _metadata\nfrom google.oauth2 import _client\n\n\nclass Credentials(credentials.ReadOnlyScoped, credentials.Credentials):\n    \"\"\"Compute Engine Credentials.\n\n    These credentials use the Google Compute Engine metadata server to obtain\n    OAuth 2.0 access tokens associated with the instance's service account.\n\n    For more information about Compute Engine authentication, including how\n    to configure scopes, see the `Compute Engine authentication\n    documentation`_.\n\n    .. note:: Compute Engine instances can be created with scopes and therefore\n        these credentials are considered to be 'scoped'. However, you can\n        not use :meth:`~google.auth.credentials.ScopedCredentials.with_scopes`\n        because it is not possible to change the scopes that the instance\n        has. Also note that\n        :meth:`~google.auth.credentials.ScopedCredentials.has_scopes` will not\n        work until the credentials have been refreshed.\n\n    .. _Compute Engine authentication documentation:\n        https://cloud.google.com/compute/docs/authentication#using\n    \"\"\"\n\n    def __init__(self, service_account_email=\"default\"):\n        \"\"\"\n        Args:\n            service_account_email (str): The service account email to use, or\n                'default'. A Compute Engine instance may have multiple service\n                accounts.\n        \"\"\"\n        super(Credentials, self).__init__()\n        self._service_account_email = service_account_email\n\n    def _retrieve_info(self, request):\n        \"\"\"Retrieve information about the service account.\n\n        Updates the scopes and retrieves the full service account email.\n\n        Args:\n            request (google.auth.transport.Request): The object used to make\n                HTTP requests.\n        \"\"\"\n        info = _metadata.get_service_account_info(\n            request, service_account=self._service_account_email\n        )\n\n        self._service_account_email = info[\"email\"]\n        self._scopes = info[\"scopes\"]\n\n    def refresh(self, request):\n        \"\"\"Refresh the access token and scopes.\n\n        Args:\n            request (google.auth.transport.Request): The object used to make\n                HTTP requests.\n\n        Raises:\n            google.auth.exceptions.RefreshError: If the Compute Engine metadata\n                service can't be reached if if the instance has not\n                credentials.\n        \"\"\"\n        try:\n            self._retrieve_info(request)\n            self.token, self.expiry = _metadata.get_service_account_token(\n                request, service_account=self._service_account_email\n            )\n        except exceptions.TransportError as caught_exc:\n            new_exc = exceptions.RefreshError(caught_exc)\n            six.raise_from(new_exc, caught_exc)\n\n    @property\n    def service_account_email(self):\n        \"\"\"The service account email.\n\n        .. note:: This is not guaranteed to be set until :meth:`refresh` has been\n            called.\n        \"\"\"\n        return self._service_account_email\n\n    @property\n    def requires_scopes(self):\n        \"\"\"False: Compute Engine credentials can not be scoped.\"\"\"\n        return False\n\n\n_DEFAULT_TOKEN_LIFETIME_SECS = 3600  # 1 hour in seconds\n_DEFAULT_TOKEN_URI = \"https://www.googleapis.com/oauth2/v4/token\"\n\n\nclass IDTokenCredentials(credentials.Credentials, credentials.Signing):\n    \"\"\"Open ID Connect ID Token-based service account credentials.\n\n    These credentials relies on the default service account of a GCE instance.\n\n    ID token can be requested from `GCE metadata server identity endpoint`_, IAM\n    token endpoint or other token endpoints you specify. If metadata server\n    identity endpoint is not used, the GCE instance must have been started with\n    a service account that has access to the IAM Cloud API.\n\n    .. _GCE metadata server identity endpoint:\n        https://cloud.google.com/compute/docs/instances/verifying-instance-identity\n    \"\"\"\n\n    def __init__(\n        self,\n        request,\n        target_audience,\n        token_uri=None,\n        additional_claims=None,\n        service_account_email=None,\n        signer=None,\n        use_metadata_identity_endpoint=False,\n    ):\n        \"\"\"\n        Args:\n            request (google.auth.transport.Request): The object used to make\n                HTTP requests.\n            target_audience (str): The intended audience for these credentials,\n                used when requesting the ID Token. The ID Token's ``aud`` claim\n                will be set to this string.\n            token_uri (str): The OAuth 2.0 Token URI.\n            additional_claims (Mapping[str, str]): Any additional claims for\n                the JWT assertion used in the authorization grant.\n            service_account_email (str): Optional explicit service account to\n                use to sign JWT tokens.\n                By default, this is the default GCE service account.\n            signer (google.auth.crypt.Signer): The signer used to sign JWTs.\n                In case the signer is specified, the request argument will be\n                ignored.\n            use_metadata_identity_endpoint (bool): Whether to use GCE metadata\n                identity endpoint. For backward compatibility the default value\n                is False. If set to True, ``token_uri``, ``additional_claims``,\n                ``service_account_email``, ``signer`` argument should not be set;\n                otherwise ValueError will be raised.\n\n        Raises:\n            ValueError:\n                If ``use_metadata_identity_endpoint`` is set to True, and one of\n                ``token_uri``, ``additional_claims``, ``service_account_email``,\n                 ``signer`` arguments is set.\n        \"\"\"\n        super(IDTokenCredentials, self).__init__()\n\n        self._use_metadata_identity_endpoint = use_metadata_identity_endpoint\n        self._target_audience = target_audience\n\n        if use_metadata_identity_endpoint:\n            if token_uri or additional_claims or service_account_email or signer:\n                raise ValueError(\n                    \"If use_metadata_identity_endpoint is set, token_uri, \"\n                    \"additional_claims, service_account_email, signer arguments\"\n                    \" must not be set\"\n                )\n            self._token_uri = None\n            self._additional_claims = None\n            self._signer = None\n\n        if service_account_email is None:\n            sa_info = _metadata.get_service_account_info(request)\n            self._service_account_email = sa_info[\"email\"]\n        else:\n            self._service_account_email = service_account_email\n\n        if not use_metadata_identity_endpoint:\n            if signer is None:\n                signer = iam.Signer(\n                    request=request,\n                    credentials=Credentials(),\n                    service_account_email=self._service_account_email,\n                )\n            self._signer = signer\n            self._token_uri = token_uri or _DEFAULT_TOKEN_URI\n\n            if additional_claims is not None:\n                self._additional_claims = additional_claims\n            else:\n                self._additional_claims = {}\n\n    def with_target_audience(self, target_audience):\n        \"\"\"Create a copy of these credentials with the specified target\n        audience.\n        Args:\n            target_audience (str): The intended audience for these credentials,\n            used when requesting the ID Token.\n        Returns:\n            google.auth.service_account.IDTokenCredentials: A new credentials\n                instance.\n        \"\"\"\n        # since the signer is already instantiated,\n        # the request is not needed\n        if self._use_metadata_identity_endpoint:\n            return self.__class__(\n                None,\n                target_audience=target_audience,\n                use_metadata_identity_endpoint=True,\n            )\n        else:\n            return self.__class__(\n                None,\n                service_account_email=self._service_account_email,\n                token_uri=self._token_uri,\n                target_audience=target_audience,\n                additional_claims=self._additional_claims.copy(),\n                signer=self.signer,\n                use_metadata_identity_endpoint=False,\n            )\n\n    def _make_authorization_grant_assertion(self):\n        \"\"\"Create the OAuth 2.0 assertion.\n        This assertion is used during the OAuth 2.0 grant to acquire an\n        ID token.\n        Returns:\n            bytes: The authorization grant assertion.\n        \"\"\"\n        now = _helpers.utcnow()\n        lifetime = datetime.timedelta(seconds=_DEFAULT_TOKEN_LIFETIME_SECS)\n        expiry = now + lifetime\n\n        payload = {\n            \"iat\": _helpers.datetime_to_secs(now),\n            \"exp\": _helpers.datetime_to_secs(expiry),\n            # The issuer must be the service account email.\n            \"iss\": self.service_account_email,\n            # The audience must be the auth token endpoint's URI\n            \"aud\": self._token_uri,\n            # The target audience specifies which service the ID token is\n            # intended for.\n            \"target_audience\": self._target_audience,\n        }\n\n        payload.update(self._additional_claims)\n\n        token = jwt.encode(self._signer, payload)\n\n        return token\n\n    def _call_metadata_identity_endpoint(self, request):\n        \"\"\"Request ID token from metadata identity endpoint.\n\n        Args:\n            request (google.auth.transport.Request): The object used to make\n                HTTP requests.\n\n        Returns:\n            Tuple[str, datetime.datetime]: The ID token and the expiry of the ID token.\n\n        Raises:\n            google.auth.exceptions.RefreshError: If the Compute Engine metadata\n                service can't be reached or if the instance has no credentials.\n            ValueError: If extracting expiry from the obtained ID token fails.\n        \"\"\"\n        try:\n            id_token = _metadata.get(\n                request,\n                \"instance/service-accounts/default/identity?audience={}&format=full\".format(\n                    self._target_audience\n                ),\n            )\n        except exceptions.TransportError as caught_exc:\n            new_exc = exceptions.RefreshError(caught_exc)\n            six.raise_from(new_exc, caught_exc)\n\n        _, payload, _, _ = jwt._unverified_decode(id_token)\n        return id_token, datetime.datetime.fromtimestamp(payload[\"exp\"])\n\n    def refresh(self, request):\n        \"\"\"Refreshes the ID token.\n\n        Args:\n            request (google.auth.transport.Request): The object used to make\n                HTTP requests.\n\n        Raises:\n            google.auth.exceptions.RefreshError: If the credentials could\n                not be refreshed.\n            ValueError: If extracting expiry from the obtained ID token fails.\n        \"\"\"\n        if self._use_metadata_identity_endpoint:\n            self.token, self.expiry = self._call_metadata_identity_endpoint(request)\n        else:\n            assertion = self._make_authorization_grant_assertion()\n            access_token, expiry, _ = _client.id_token_jwt_grant(\n                request, self._token_uri, assertion\n            )\n            self.token = access_token\n            self.expiry = expiry\n\n    @property\n    @_helpers.copy_docstring(credentials.Signing)\n    def signer(self):\n        return self._signer\n\n    def sign_bytes(self, message):\n        \"\"\"Signs the given message.\n\n        Args:\n            message (bytes): The message to sign.\n\n        Returns:\n            bytes: The message's cryptographic signature.\n\n        Raises:\n            ValueError:\n                Signer is not available if metadata identity endpoint is used.\n        \"\"\"\n        if self._use_metadata_identity_endpoint:\n            raise ValueError(\n                \"Signer is not available if metadata identity endpoint is used\"\n            )\n        return self._signer.sign(message)\n\n    @property\n    def service_account_email(self):\n        \"\"\"The service account email.\"\"\"\n        return self._service_account_email\n\n    @property\n    def signer_email(self):\n        return self._service_account_email\n", "path": "google/auth/compute_engine/credentials.py"}]}