4949
5050# The Google OAuth 2.0 token endpoint. Used for authorized user credentials.
5151_GOOGLE_OAUTH2_TOKEN_ENDPOINT = "https://oauth2.googleapis.com/token"
52+ _DEFAULT_UNIVERSE_DOMAIN = "googleapis.com"
5253
5354
5455class Credentials (credentials .ReadOnlyScoped , credentials .CredentialsWithQuotaProject ):
@@ -85,6 +86,7 @@ def __init__(
8586 enable_reauth_refresh = False ,
8687 granted_scopes = None ,
8788 trust_boundary = None ,
89+ universe_domain = _DEFAULT_UNIVERSE_DOMAIN ,
8890 ):
8991 """
9092 Args:
@@ -126,6 +128,9 @@ def __init__(
126128 granted_scopes (Optional[Sequence[str]]): The scopes that were consented/granted by the user.
127129 This could be different from the requested scopes and it could be empty if granted
128130 and requested scopes were same.
131+ trust_boundary (str): String representation of trust boundary meta.
132+ universe_domain (Optional[str]): The universe domain. The default
133+ universe domain is googleapis.com.
129134 """
130135 super (Credentials , self ).__init__ ()
131136 self .token = token
@@ -143,6 +148,7 @@ def __init__(
143148 self .refresh_handler = refresh_handler
144149 self ._enable_reauth_refresh = enable_reauth_refresh
145150 self ._trust_boundary = trust_boundary
151+ self ._universe_domain = universe_domain or _DEFAULT_UNIVERSE_DOMAIN
146152
147153 def __getstate__ (self ):
148154 """A __getstate__ method must exist for the __setstate__ to be called
@@ -273,6 +279,7 @@ def with_quota_project(self, quota_project_id):
273279 rapt_token = self .rapt_token ,
274280 enable_reauth_refresh = self ._enable_reauth_refresh ,
275281 trust_boundary = self ._trust_boundary ,
282+ universe_domain = self ._universe_domain ,
276283 )
277284
278285 @_helpers .copy_docstring (credentials .CredentialsWithTokenUri )
@@ -292,13 +299,52 @@ def with_token_uri(self, token_uri):
292299 rapt_token = self .rapt_token ,
293300 enable_reauth_refresh = self ._enable_reauth_refresh ,
294301 trust_boundary = self ._trust_boundary ,
302+ universe_domain = self ._universe_domain ,
303+ )
304+
305+ def with_universe_domain (self , universe_domain ):
306+ """Create a copy of the credential with the given universe domain.
307+
308+ Args:
309+ universe_domain (str): The universe domain value.
310+
311+ Returns:
312+ google.oauth2.credentials.Credentials: A new credentials instance.
313+ """
314+
315+ return self .__class__ (
316+ self .token ,
317+ refresh_token = self .refresh_token ,
318+ id_token = self .id_token ,
319+ token_uri = self ._token_uri ,
320+ client_id = self .client_id ,
321+ client_secret = self .client_secret ,
322+ scopes = self .scopes ,
323+ default_scopes = self .default_scopes ,
324+ granted_scopes = self .granted_scopes ,
325+ quota_project_id = self .quota_project_id ,
326+ rapt_token = self .rapt_token ,
327+ enable_reauth_refresh = self ._enable_reauth_refresh ,
328+ trust_boundary = self ._trust_boundary ,
329+ universe_domain = universe_domain ,
295330 )
296331
297332 def _metric_header_for_usage (self ):
298333 return metrics .CRED_TYPE_USER
299334
300335 @_helpers .copy_docstring (credentials .Credentials )
301336 def refresh (self , request ):
337+ if self ._universe_domain != _DEFAULT_UNIVERSE_DOMAIN :
338+ raise exceptions .RefreshError (
339+ "User credential refresh is only supported in the default "
340+ "googleapis.com universe domain, but the current universe "
341+ "domain is {}. If you created the credential with an access "
342+ "token, it's likely that the provided token is expired now, "
343+ "please update your code with a valid token." .format (
344+ self ._universe_domain
345+ )
346+ )
347+
302348 scopes = self ._scopes if self ._scopes is not None else self ._default_scopes
303349 # Use refresh handler if available and no refresh token is
304350 # available. This is useful in general when tokens are obtained by calling
@@ -428,6 +474,7 @@ def from_authorized_user_info(cls, info, scopes=None):
428474 expiry = expiry ,
429475 rapt_token = info .get ("rapt_token" ), # may not exist
430476 trust_boundary = info .get ("trust_boundary" ), # may not exist
477+ universe_domain = info .get ("universe_domain" ), # may not exist
431478 )
432479
433480 @classmethod
@@ -471,6 +518,7 @@ def to_json(self, strip=None):
471518 "client_secret" : self .client_secret ,
472519 "scopes" : self .scopes ,
473520 "rapt_token" : self .rapt_token ,
521+ "universe_domain" : self ._universe_domain ,
474522 }
475523 if self .expiry : # flatten expiry timestamp
476524 prep ["expiry" ] = self .expiry .isoformat () + "Z"
0 commit comments