2525from google .api_core import retry as retries # type: ignore
2626from google .api_core import operations_v1 # type: ignore
2727from google .auth import credentials as ga_credentials # type: ignore
28+ from google .oauth2 import service_account # type: ignore
2829
2930from google .cloud .documentai_v1beta2 .types import document
3031from google .cloud .documentai_v1beta2 .types import document_understanding
4849 except pkg_resources .DistributionNotFound : # pragma: NO COVER
4950 _GOOGLE_AUTH_VERSION = None
5051
51- _API_CORE_VERSION = google .api_core .__version__
52-
5352
5453class DocumentUnderstandingServiceTransport (abc .ABC ):
5554 """Abstract transport class for DocumentUnderstandingService."""
@@ -67,6 +66,7 @@ def __init__(
6766 scopes : Optional [Sequence [str ]] = None ,
6867 quota_project_id : Optional [str ] = None ,
6968 client_info : gapic_v1 .client_info .ClientInfo = DEFAULT_CLIENT_INFO ,
69+ always_use_jwt_access : Optional [bool ] = False ,
7070 ** kwargs ,
7171 ) -> None :
7272 """Instantiate the transport.
@@ -90,6 +90,8 @@ def __init__(
9090 API requests. If ``None``, then default info will be used.
9191 Generally, you only need to set this if you're developing
9292 your own client library.
93+ always_use_jwt_access (Optional[bool]): Whether self signed JWT should
94+ be used for service account credentials.
9395 """
9496 # Save the hostname. Default to port 443 (HTTPS) if none is specified.
9597 if ":" not in host :
@@ -99,7 +101,7 @@ def __init__(
99101 scopes_kwargs = self ._get_scopes_kwargs (self ._host , scopes )
100102
101103 # Save the scopes.
102- self ._scopes = scopes or self . AUTH_SCOPES
104+ self ._scopes = scopes
103105
104106 # If no credentials are provided, then determine the appropriate
105107 # defaults.
@@ -118,13 +120,20 @@ def __init__(
118120 ** scopes_kwargs , quota_project_id = quota_project_id
119121 )
120122
123+ # If the credentials is service account credentials, then always try to use self signed JWT.
124+ if (
125+ always_use_jwt_access
126+ and isinstance (credentials , service_account .Credentials )
127+ and hasattr (service_account .Credentials , "with_always_use_jwt_access" )
128+ ):
129+ credentials = credentials .with_always_use_jwt_access (True )
130+
121131 # Save the credentials.
122132 self ._credentials = credentials
123133
124- # TODO(busunkim): These two class methods are in the base transport
134+ # TODO(busunkim): This method is in the base transport
125135 # to avoid duplicating code across the transport classes. These functions
126- # should be deleted once the minimum required versions of google-api-core
127- # and google-auth are increased.
136+ # should be deleted once the minimum required versions of google-auth is increased.
128137
129138 # TODO: Remove this function once google-auth >= 1.25.0 is required
130139 @classmethod
@@ -139,33 +148,20 @@ def _get_scopes_kwargs(
139148 packaging .version .parse (_GOOGLE_AUTH_VERSION )
140149 >= packaging .version .parse ("1.25.0" )
141150 ):
142- scopes_kwargs = {"scopes" : scopes , "default_scopes" : cls .AUTH_SCOPES }
151+ # Documentai uses a regional host (us-documentai.googleapis.com) as the default
152+ # so self-signed JWT cannot be used.
153+ # Intentionally pass default scopes as user scopes so the auth library
154+ # does not use the self-signed JWT flow.
155+ # https://github.com/googleapis/python-documentai/issues/174
156+ scopes_kwargs = {
157+ "scopes" : scopes or cls .AUTH_SCOPES ,
158+ "default_scopes" : cls .AUTH_SCOPES ,
159+ }
143160 else :
144161 scopes_kwargs = {"scopes" : scopes or cls .AUTH_SCOPES }
145162
146163 return scopes_kwargs
147164
148- # TODO: Remove this function once google-api-core >= 1.26.0 is required
149- @classmethod
150- def _get_self_signed_jwt_kwargs (
151- cls , host : str , scopes : Optional [Sequence [str ]]
152- ) -> Dict [str , Union [Optional [Sequence [str ]], str ]]:
153- """Returns kwargs to pass to grpc_helpers.create_channel depending on the google-api-core version"""
154-
155- self_signed_jwt_kwargs : Dict [str , Union [Optional [Sequence [str ]], str ]] = {}
156-
157- if _API_CORE_VERSION and (
158- packaging .version .parse (_API_CORE_VERSION )
159- >= packaging .version .parse ("1.26.0" )
160- ):
161- self_signed_jwt_kwargs ["default_scopes" ] = cls .AUTH_SCOPES
162- self_signed_jwt_kwargs ["scopes" ] = scopes
163- self_signed_jwt_kwargs ["default_host" ] = cls .DEFAULT_HOST
164- else :
165- self_signed_jwt_kwargs ["scopes" ] = scopes or cls .AUTH_SCOPES
166-
167- return self_signed_jwt_kwargs
168-
169165 def _prep_wrapped_messages (self , client_info ):
170166 # Precompute the wrapped methods.
171167 self ._wrapped_methods = {
0 commit comments