From cdcb249deedd33f31fdba4289bdc8d72de486514 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 23 Apr 2026 17:16:10 -0700 Subject: [PATCH 1/9] allow passing single string scopes --- packages/google-auth/google/auth/_default.py | 4 +-- .../google-auth/google/auth/app_engine.py | 6 ++-- .../google-auth/google/auth/credentials.py | 28 ++++++++++++++----- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/packages/google-auth/google/auth/_default.py b/packages/google-auth/google/auth/_default.py index cb40c1fa6d77..112fb5d99b7e 100644 --- a/packages/google-auth/google/auth/_default.py +++ b/packages/google-auth/google/auth/_default.py @@ -591,7 +591,7 @@ def _apply_quota_project_id(credentials, quota_project_id): def default( - scopes: Optional[Sequence[str]] = None, + scopes: Optional[Sequence[str] | str] = None, request: Optional["google.auth.transport.Request"] = None, quota_project_id: Optional[str] = None, default_scopes: Optional[Sequence[str]] = None, @@ -666,7 +666,7 @@ def default( credentials, project_id = google.auth.default() Args: - scopes (Sequence[str]): The list of scopes for the credentials. If + scopes (Optional[Sequence[str] | str]): The list of scopes for the credentials. If specified, the credentials will automatically be scoped if necessary. request (Optional[google.auth.transport.Request]): An object used to make diff --git a/packages/google-auth/google/auth/app_engine.py b/packages/google-auth/google/auth/app_engine.py index 49f6457f4af1..4b151fa0f627 100644 --- a/packages/google-auth/google/auth/app_engine.py +++ b/packages/google-auth/google/auth/app_engine.py @@ -95,11 +95,11 @@ def __init__( ): """ Args: - scopes (Sequence[str]): Scopes to request from the App Identity + scopes (Optional[Sequence[str]]): Scopes to request from the App Identity API. - default_scopes (Sequence[str]): Default scopes passed by a + default_scopes (Optional[Sequence[str]]): Default scopes passed by a Google client library. Use 'scopes' for user-defined scopes. - service_account_id (str): The service account ID passed into + service_account_id (Optional[str]): The service account ID passed into :func:`google.appengine.api.app_identity.get_access_token`. If not specified, the default application service account ID will be used. diff --git a/packages/google-auth/google/auth/credentials.py b/packages/google-auth/google/auth/credentials.py index cdb20653277b..2f8c689c65cb 100644 --- a/packages/google-auth/google/auth/credentials.py +++ b/packages/google-auth/google/auth/credentials.py @@ -19,7 +19,7 @@ from enum import Enum import logging import os -from typing import List +from typing import List, Optional, Sequence, Union from google.auth import _helpers, environment_vars from google.auth import exceptions @@ -579,12 +579,18 @@ class Scoped(ReadOnlyScoped): """ @abc.abstractmethod - def with_scopes(self, scopes, default_scopes=None): + def with_scopes( + self, + scopes: Optional[Sequence[str]], + default_scopes: Optional[Sequence[str]] = None, + ): """Create a copy of these credentials with the specified scopes. Args: - scopes (Sequence[str]): The list of scopes to attach to the + scopes (Optional[Sequence[str]]): The list of scopes to attach to the current credentials. + default_scopes (Optional[Sequence[str]]): Default scopes passed by a + Google client library. Use 'scopes' for user-defined scopes. Raises: NotImplementedError: If the credentials' scopes can not be changed. @@ -594,7 +600,11 @@ def with_scopes(self, scopes, default_scopes=None): raise NotImplementedError("This class does not require scoping.") -def with_scopes_if_required(credentials, scopes, default_scopes=None): +def with_scopes_if_required( + credentials, + scopes: Optional[Union[str, Sequence[str]]], + default_scopes: Optional[Sequence[str]] = None, +): """Creates a copy of the credentials with scopes if scoping is required. This helper function is useful when you do not know (or care to know) the @@ -607,8 +617,8 @@ def with_scopes_if_required(credentials, scopes, default_scopes=None): Args: credentials (google.auth.credentials.Credentials): The credentials to scope if necessary. - scopes (Sequence[str]): The list of scopes to use. - default_scopes (Sequence[str]): Default scopes passed by a + scopes (Optional[Sequence[str] | str]): The list of scopes to use. + default_scopes (Optional[Sequence[str]]): Default scopes passed by a Google client library. Use 'scopes' for user-defined scopes. Returns: @@ -616,8 +626,12 @@ def with_scopes_if_required(credentials, scopes, default_scopes=None): credentials, or the passed in credentials instance if no scoping was required. """ + # wrap single-string scopes in a list + scopes_seq: Optional[Sequence[str]] = ( + [scopes] if isinstance(scopes, str) else scopes + ) if isinstance(credentials, Scoped) and credentials.requires_scopes: - return credentials.with_scopes(scopes, default_scopes=default_scopes) + return credentials.with_scopes(scopes_seq, default_scopes=default_scopes) else: return credentials From da7af3f6ff4065c3db5d7ea02531b23a85fa06da Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 23 Apr 2026 17:44:43 -0700 Subject: [PATCH 2/9] added types to Credentials attributes --- packages/google-auth/google/auth/credentials.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/google-auth/google/auth/credentials.py b/packages/google-auth/google/auth/credentials.py index 2f8c689c65cb..6beac3558ea8 100644 --- a/packages/google-auth/google/auth/credentials.py +++ b/packages/google-auth/google/auth/credentials.py @@ -16,6 +16,7 @@ """Interfaces for credentials.""" import abc +import datetime from enum import Enum import logging import os @@ -56,16 +57,16 @@ class Credentials(_BaseCredentials): def __init__(self): super(Credentials, self).__init__() - self.expiry = None + self.expiry: Optional[datetime.datetime] = None """Optional[datetime]: When the token expires and is no longer valid. If this is None, the token is assumed to never expire.""" - self._quota_project_id = None + self._quota_project_id: Optional[str] = None """Optional[str]: Project to use for quota and billing purposes.""" - self._trust_boundary = None + self._trust_boundary: Optional[dict] = None """Optional[dict]: Cache of a trust boundary response which has a list of allowed regions and an encoded string representation of credentials trust boundary.""" - self._universe_domain = DEFAULT_UNIVERSE_DOMAIN + self._universe_domain: Optional[str] = DEFAULT_UNIVERSE_DOMAIN """Optional[str]: The universe domain value, default is googleapis.com """ From 69c076a72803f8e2ee74a254381864692096a5f7 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 23 Apr 2026 18:05:30 -0700 Subject: [PATCH 3/9] fixed lint --- packages/google-auth/google/auth/credentials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google-auth/google/auth/credentials.py b/packages/google-auth/google/auth/credentials.py index ad1310818f43..a572dff0bae2 100644 --- a/packages/google-auth/google/auth/credentials.py +++ b/packages/google-auth/google/auth/credentials.py @@ -20,7 +20,7 @@ from enum import Enum import logging import os -from typing import Dict List, Optional, Sequence, Union, TYPE_CHECKING +from typing import Dict, List, Optional, Sequence, TYPE_CHECKING, Union from urllib.parse import urlparse import warnings From 3cc9041695a9379468974082799477e90a80c012 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Thu, 23 Apr 2026 18:23:40 -0700 Subject: [PATCH 4/9] fixed typos --- packages/google-auth/google/auth/crypt/rsa.py | 2 +- packages/google-auth/google/auth/transport/_mtls_helper.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/google-auth/google/auth/crypt/rsa.py b/packages/google-auth/google/auth/crypt/rsa.py index 639be9069549..efadd72e960a 100644 --- a/packages/google-auth/google/auth/crypt/rsa.py +++ b/packages/google-auth/google/auth/crypt/rsa.py @@ -16,7 +16,7 @@ RSA cryptography signer and verifier. This file provides a shared wrapper, that defers to _python_rsa or _cryptography_rsa -for implmentations using different third party libraries +for implementations using different third party libraries """ from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey diff --git a/packages/google-auth/google/auth/transport/_mtls_helper.py b/packages/google-auth/google/auth/transport/_mtls_helper.py index d6450291c7f2..75016384bbc3 100644 --- a/packages/google-auth/google/auth/transport/_mtls_helper.py +++ b/packages/google-auth/google/auth/transport/_mtls_helper.py @@ -50,7 +50,7 @@ b"-----BEGIN PASSPHRASE-----(.+)-----END PASSPHRASE-----", re.DOTALL ) -# Temporary patch to accomodate incorrect cert config in Cloud Run prod environment. +# Temporary patch to accommodate incorrect cert config in Cloud Run prod environment. _WELL_KNOWN_CLOUD_RUN_CERT_PATH = ( "/var/run/secrets/workload-spiffe-credentials/certificates.pem" ) From fbe2bd764af28303af3a9242d1778e4b6a17eb3a Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Fri, 24 Apr 2026 12:43:47 -0700 Subject: [PATCH 5/9] Update packages/google-auth/google/auth/_default.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- packages/google-auth/google/auth/_default.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google-auth/google/auth/_default.py b/packages/google-auth/google/auth/_default.py index 112fb5d99b7e..8a3af9db56b6 100644 --- a/packages/google-auth/google/auth/_default.py +++ b/packages/google-auth/google/auth/_default.py @@ -591,7 +591,7 @@ def _apply_quota_project_id(credentials, quota_project_id): def default( - scopes: Optional[Sequence[str] | str] = None, + scopes: Optional[Union[Sequence[str], str]] = None, request: Optional["google.auth.transport.Request"] = None, quota_project_id: Optional[str] = None, default_scopes: Optional[Sequence[str]] = None, From c0de7277c57303e54df6c2d0f091f669ff3d9599 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Fri, 24 Apr 2026 12:43:54 -0700 Subject: [PATCH 6/9] Update packages/google-auth/google/auth/_default.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- packages/google-auth/google/auth/_default.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google-auth/google/auth/_default.py b/packages/google-auth/google/auth/_default.py index 8a3af9db56b6..be770ca81bf2 100644 --- a/packages/google-auth/google/auth/_default.py +++ b/packages/google-auth/google/auth/_default.py @@ -666,7 +666,7 @@ def default( credentials, project_id = google.auth.default() Args: - scopes (Optional[Sequence[str] | str]): The list of scopes for the credentials. If + scopes (Optional[Union[Sequence[str], str]]): The list of scopes for the credentials. If specified, the credentials will automatically be scoped if necessary. request (Optional[google.auth.transport.Request]): An object used to make From d821ae88b8f86a1b5d9caa3819bf916b5305646a Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Fri, 24 Apr 2026 12:45:00 -0700 Subject: [PATCH 7/9] Update packages/google-auth/google/auth/credentials.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- packages/google-auth/google/auth/credentials.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google-auth/google/auth/credentials.py b/packages/google-auth/google/auth/credentials.py index a572dff0bae2..0e7bfdf4b91a 100644 --- a/packages/google-auth/google/auth/credentials.py +++ b/packages/google-auth/google/auth/credentials.py @@ -618,7 +618,7 @@ class Scoped(ReadOnlyScoped): @abc.abstractmethod def with_scopes( - self, + scopes (Optional[Union[str, Sequence[str]]]): The list of scopes to use. scopes: Optional[Sequence[str]], default_scopes: Optional[Sequence[str]] = None, ): From 6171052b6bdecac955471a670daa27cde7b3e30e Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Fri, 24 Apr 2026 12:47:55 -0700 Subject: [PATCH 8/9] fixed bad apply --- packages/google-auth/google/auth/credentials.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/google-auth/google/auth/credentials.py b/packages/google-auth/google/auth/credentials.py index 0e7bfdf4b91a..34fee12fc102 100644 --- a/packages/google-auth/google/auth/credentials.py +++ b/packages/google-auth/google/auth/credentials.py @@ -618,7 +618,7 @@ class Scoped(ReadOnlyScoped): @abc.abstractmethod def with_scopes( - scopes (Optional[Union[str, Sequence[str]]]): The list of scopes to use. + self, scopes: Optional[Sequence[str]], default_scopes: Optional[Sequence[str]] = None, ): @@ -655,7 +655,7 @@ def with_scopes_if_required( Args: credentials (google.auth.credentials.Credentials): The credentials to scope if necessary. - scopes (Optional[Sequence[str] | str]): The list of scopes to use. + scopes (Optional[Union[str, Sequence[str]]]): The list of scopes to use. default_scopes (Optional[Sequence[str]]): Default scopes passed by a Google client library. Use 'scopes' for user-defined scopes. From 2acbd528d154ae724bcddbd35d17885307201615 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Fri, 24 Apr 2026 12:57:09 -0700 Subject: [PATCH 9/9] fix lint --- packages/google-auth/google/auth/_default.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google-auth/google/auth/_default.py b/packages/google-auth/google/auth/_default.py index be770ca81bf2..9fb6da1f2b5f 100644 --- a/packages/google-auth/google/auth/_default.py +++ b/packages/google-auth/google/auth/_default.py @@ -22,7 +22,7 @@ import json import logging import os -from typing import Optional, Sequence, TYPE_CHECKING +from typing import Optional, Sequence, TYPE_CHECKING, Union import warnings from google.auth import environment_vars