diff --git a/google/auth/_helpers.py b/google/auth/_helpers.py index 4a69d4c61..1e92c41bd 100644 --- a/google/auth/_helpers.py +++ b/google/auth/_helpers.py @@ -124,6 +124,26 @@ def utcnow(): return now +def utcfromtimestamp(timestamp): + """Returns the UTC datetime from a timestamp. + + Args: + timestamp (float): The timestamp to convert. + + Returns: + datetime: The time in UTC. + """ + # We used datetime.utcfromtimestamp() before, since it's deprecated from + # python 3.12, we are using datetime.fromtimestamp(timestamp, timezone.utc) + # now. "utcfromtimestamp()" is offset-native (no timezone info), but + # "fromtimestamp(timestamp, timezone.utc)" is offset-aware (with timezone + # info). This will cause datetime comparison problem. For backward + # compatibility, we need to remove the timezone info. + dt = datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc) + dt = dt.replace(tzinfo=None) + return dt + + def datetime_to_secs(value): """Convert a datetime object to the number of seconds since the UNIX epoch. diff --git a/google/auth/app_engine.py b/google/auth/app_engine.py index 7083ee614..c599f260c 100644 --- a/google/auth/app_engine.py +++ b/google/auth/app_engine.py @@ -128,7 +128,7 @@ def refresh(self, request): scopes = self._scopes if self._scopes is not None else self._default_scopes # pylint: disable=unused-argument token, ttl = app_identity.get_access_token(scopes, self._service_account_id) - expiry = datetime.datetime.utcfromtimestamp(ttl) + expiry = _helpers.utcfromtimestamp(ttl) self.token, self.expiry = token, expiry diff --git a/google/auth/compute_engine/credentials.py b/google/auth/compute_engine/credentials.py index a9ed6656c..bfff98f39 100644 --- a/google/auth/compute_engine/credentials.py +++ b/google/auth/compute_engine/credentials.py @@ -498,7 +498,7 @@ def _call_metadata_identity_endpoint(self, request): raise new_exc from caught_exc _, payload, _, _ = jwt._unverified_decode(id_token) - return id_token, datetime.datetime.utcfromtimestamp(payload["exp"]) + return id_token, _helpers.utcfromtimestamp(payload["exp"]) def refresh(self, request): """Refreshes the ID token. diff --git a/google/auth/impersonated_credentials.py b/google/auth/impersonated_credentials.py index 8ac0a420e..9eaa26d5e 100644 --- a/google/auth/impersonated_credentials.py +++ b/google/auth/impersonated_credentials.py @@ -27,7 +27,7 @@ import base64 import copy -from datetime import datetime +from datetime import datetime, timezone import http.client as http_client import json @@ -649,7 +649,7 @@ def refresh(self, request): raise new_exc from caught_exc self.token = id_token - self.expiry = datetime.utcfromtimestamp( + self.expiry = _helpers.utcfromtimestamp( jwt.decode(id_token, verify=False)["exp"] ) diff --git a/google/oauth2/_client.py b/google/oauth2/_client.py index b2fe982e5..d4db42007 100644 --- a/google/oauth2/_client.py +++ b/google/oauth2/_client.py @@ -368,7 +368,7 @@ def call_iam_generate_id_token_endpoint( raise new_exc from caught_exc payload = jwt.decode(id_token, verify=False) - expiry = datetime.datetime.utcfromtimestamp(payload["exp"]) + expiry = _helpers.utcfromtimestamp(payload["exp"]) return id_token, expiry @@ -420,7 +420,7 @@ def id_token_jwt_grant(request, token_uri, assertion, can_retry=True): raise new_exc from caught_exc payload = jwt.decode(id_token, verify=False) - expiry = datetime.datetime.utcfromtimestamp(payload["exp"]) + expiry = _helpers.utcfromtimestamp(payload["exp"]) return id_token, expiry, response_data diff --git a/google/oauth2/_client_async.py b/google/oauth2/_client_async.py index 768f8eac2..ec98f28d4 100644 --- a/google/oauth2/_client_async.py +++ b/google/oauth2/_client_async.py @@ -29,6 +29,7 @@ import urllib from google.auth import _exponential_backoff +from google.auth import _helpers from google.auth import exceptions from google.auth import jwt from google.oauth2 import _client as client @@ -227,7 +228,7 @@ async def id_token_jwt_grant(request, token_uri, assertion, can_retry=True): raise new_exc from caught_exc payload = jwt.decode(id_token, verify=False) - expiry = datetime.datetime.utcfromtimestamp(payload["exp"]) + expiry = _helpers.utcfromtimestamp(payload["exp"]) return id_token, expiry, response_data