mirror of
https://github.com/GAM-team/GAM.git
synced 2025-07-10 14:43:34 +00:00
Update google libraries
This commit is contained in:
@ -18,13 +18,9 @@ import json
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from google.auth import environment_vars
|
from google.auth import environment_vars
|
||||||
import google.oauth2.credentials
|
import google.oauth2.credentials
|
||||||
|
|
||||||
# The Google OAuth 2.0 token endpoint. Used for authorized user credentials.
|
|
||||||
_GOOGLE_OAUTH2_TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token'
|
|
||||||
|
|
||||||
# The ~/.config subdirectory containing gcloud credentials.
|
# The ~/.config subdirectory containing gcloud credentials.
|
||||||
_CONFIG_DIRECTORY = 'gcloud'
|
_CONFIG_DIRECTORY = 'gcloud'
|
||||||
@ -94,20 +90,8 @@ def load_authorized_user_credentials(info):
|
|||||||
Raises:
|
Raises:
|
||||||
ValueError: if the info is in the wrong format or missing data.
|
ValueError: if the info is in the wrong format or missing data.
|
||||||
"""
|
"""
|
||||||
keys_needed = set(('refresh_token', 'client_id', 'client_secret'))
|
return google.oauth2.credentials.Credentials.from_authorized_user_info(
|
||||||
missing = keys_needed.difference(six.iterkeys(info))
|
info)
|
||||||
|
|
||||||
if missing:
|
|
||||||
raise ValueError(
|
|
||||||
'Authorized user info was not in the expected format, missing '
|
|
||||||
'fields {}.'.format(', '.join(missing)))
|
|
||||||
|
|
||||||
return google.oauth2.credentials.Credentials(
|
|
||||||
None, # No access token, must be refreshed.
|
|
||||||
refresh_token=info['refresh_token'],
|
|
||||||
token_uri=_GOOGLE_OAUTH2_TOKEN_ENDPOINT,
|
|
||||||
client_id=info['client_id'],
|
|
||||||
client_secret=info['client_secret'])
|
|
||||||
|
|
||||||
|
|
||||||
def get_project_id():
|
def get_project_id():
|
||||||
|
@ -22,6 +22,8 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
from google.auth import environment_vars
|
from google.auth import environment_vars
|
||||||
from google.auth import exceptions
|
from google.auth import exceptions
|
||||||
import google.auth.transport._http_client
|
import google.auth.transport._http_client
|
||||||
@ -67,9 +69,11 @@ def _load_credentials_from_file(filename):
|
|||||||
with io.open(filename, 'r') as file_obj:
|
with io.open(filename, 'r') as file_obj:
|
||||||
try:
|
try:
|
||||||
info = json.load(file_obj)
|
info = json.load(file_obj)
|
||||||
except ValueError as exc:
|
except ValueError as caught_exc:
|
||||||
raise exceptions.DefaultCredentialsError(
|
new_exc = exceptions.DefaultCredentialsError(
|
||||||
'File {} is not a valid json file.'.format(filename), exc)
|
'File {} is not a valid json file.'.format(filename),
|
||||||
|
caught_exc)
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
|
|
||||||
# The type key should indicate that the file is either a service account
|
# The type key should indicate that the file is either a service account
|
||||||
# credentials file or an authorized user credentials file.
|
# credentials file or an authorized user credentials file.
|
||||||
@ -80,10 +84,11 @@ def _load_credentials_from_file(filename):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
credentials = _cloud_sdk.load_authorized_user_credentials(info)
|
credentials = _cloud_sdk.load_authorized_user_credentials(info)
|
||||||
except ValueError as exc:
|
except ValueError as caught_exc:
|
||||||
raise exceptions.DefaultCredentialsError(
|
msg = 'Failed to load authorized user credentials from {}'.format(
|
||||||
'Failed to load authorized user credentials from {}'.format(
|
filename)
|
||||||
filename), exc)
|
new_exc = exceptions.DefaultCredentialsError(msg, caught_exc)
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
# Authorized user credentials do not contain the project ID.
|
# Authorized user credentials do not contain the project ID.
|
||||||
return credentials, None
|
return credentials, None
|
||||||
|
|
||||||
@ -93,10 +98,11 @@ def _load_credentials_from_file(filename):
|
|||||||
try:
|
try:
|
||||||
credentials = (
|
credentials = (
|
||||||
service_account.Credentials.from_service_account_info(info))
|
service_account.Credentials.from_service_account_info(info))
|
||||||
except ValueError as exc:
|
except ValueError as caught_exc:
|
||||||
raise exceptions.DefaultCredentialsError(
|
msg = 'Failed to load service account credentials from {}'.format(
|
||||||
'Failed to load service account credentials from {}'.format(
|
filename)
|
||||||
filename), exc)
|
new_exc = exceptions.DefaultCredentialsError(msg, caught_exc)
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
return credentials, info.get('project_id')
|
return credentials, info.get('project_id')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -123,12 +129,6 @@ def _get_gcloud_sdk_credentials():
|
|||||||
if not project_id:
|
if not project_id:
|
||||||
project_id = _cloud_sdk.get_project_id()
|
project_id = _cloud_sdk.get_project_id()
|
||||||
|
|
||||||
if not project_id:
|
|
||||||
_LOGGER.warning(
|
|
||||||
'No project ID could be determined from the Cloud SDK '
|
|
||||||
'configuration. Consider running `gcloud config set project` or '
|
|
||||||
'setting the %s environment variable', environment_vars.PROJECT)
|
|
||||||
|
|
||||||
return credentials, project_id
|
return credentials, project_id
|
||||||
|
|
||||||
|
|
||||||
@ -141,12 +141,6 @@ def _get_explicit_environ_credentials():
|
|||||||
credentials, project_id = _load_credentials_from_file(
|
credentials, project_id = _load_credentials_from_file(
|
||||||
os.environ[environment_vars.CREDENTIALS])
|
os.environ[environment_vars.CREDENTIALS])
|
||||||
|
|
||||||
if not project_id:
|
|
||||||
_LOGGER.warning(
|
|
||||||
'No project ID could be determined from the credentials at %s '
|
|
||||||
'Consider setting the %s environment variable',
|
|
||||||
environment_vars.CREDENTIALS, environment_vars.PROJECT)
|
|
||||||
|
|
||||||
return credentials, project_id
|
return credentials, project_id
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -182,10 +176,6 @@ def _get_gce_credentials(request=None):
|
|||||||
try:
|
try:
|
||||||
project_id = _metadata.get_project_id(request=request)
|
project_id = _metadata.get_project_id(request=request)
|
||||||
except exceptions.TransportError:
|
except exceptions.TransportError:
|
||||||
_LOGGER.warning(
|
|
||||||
'No project ID could be determined from the Compute Engine '
|
|
||||||
'metadata service. Consider setting the %s environment '
|
|
||||||
'variable.', environment_vars.PROJECT)
|
|
||||||
project_id = None
|
project_id = None
|
||||||
|
|
||||||
return compute_engine.Credentials(), project_id
|
return compute_engine.Credentials(), project_id
|
||||||
@ -281,6 +271,13 @@ def default(scopes=None, request=None):
|
|||||||
credentials, project_id = checker()
|
credentials, project_id = checker()
|
||||||
if credentials is not None:
|
if credentials is not None:
|
||||||
credentials = with_scopes_if_required(credentials, scopes)
|
credentials = with_scopes_if_required(credentials, scopes)
|
||||||
return credentials, explicit_project_id or project_id
|
effective_project_id = explicit_project_id or project_id
|
||||||
|
if not effective_project_id:
|
||||||
|
_LOGGER.warning(
|
||||||
|
'No project ID could be determined. Consider running '
|
||||||
|
'`gcloud config set project` or setting the %s '
|
||||||
|
'environment variable',
|
||||||
|
environment_vars.PROJECT)
|
||||||
|
return credentials, effective_project_id
|
||||||
|
|
||||||
raise exceptions.DefaultCredentialsError(_HELP_MESSAGE)
|
raise exceptions.DefaultCredentialsError(_HELP_MESSAGE)
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
from google.auth import _helpers
|
from google.auth import _helpers
|
||||||
import google.auth.app_engine
|
import google.auth.app_engine
|
||||||
import google.oauth2.credentials
|
import google.oauth2.credentials
|
||||||
@ -30,8 +32,9 @@ try:
|
|||||||
import oauth2client.client
|
import oauth2client.client
|
||||||
import oauth2client.contrib.gce
|
import oauth2client.contrib.gce
|
||||||
import oauth2client.service_account
|
import oauth2client.service_account
|
||||||
except ImportError:
|
except ImportError as caught_exc:
|
||||||
raise ImportError('oauth2client is not installed.')
|
six.raise_from(
|
||||||
|
ImportError('oauth2client is not installed.'), caught_exc)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import oauth2client.contrib.appengine
|
import oauth2client.contrib.appengine
|
||||||
@ -162,5 +165,6 @@ def convert(credentials):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
return _CLASS_CONVERSION_MAP[credentials_class](credentials)
|
return _CLASS_CONVERSION_MAP[credentials_class](credentials)
|
||||||
except KeyError:
|
except KeyError as caught_exc:
|
||||||
raise ValueError(_CONVERT_ERROR_TMPL.format(credentials_class))
|
new_exc = ValueError(_CONVERT_ERROR_TMPL.format(credentials_class))
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
|
@ -22,6 +22,7 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import six
|
||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
from six.moves.urllib import parse as urlparse
|
from six.moves.urllib import parse as urlparse
|
||||||
|
|
||||||
@ -118,10 +119,11 @@ def get(request, path, root=_METADATA_ROOT, recursive=False):
|
|||||||
if response.headers['content-type'] == 'application/json':
|
if response.headers['content-type'] == 'application/json':
|
||||||
try:
|
try:
|
||||||
return json.loads(content)
|
return json.loads(content)
|
||||||
except ValueError:
|
except ValueError as caught_exc:
|
||||||
raise exceptions.TransportError(
|
new_exc = exceptions.TransportError(
|
||||||
'Received invalid JSON from the Google Compute Engine'
|
'Received invalid JSON from the Google Compute Engine'
|
||||||
'metadata service: {:.20}'.format(content))
|
'metadata service: {:.20}'.format(content))
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
else:
|
else:
|
||||||
return content
|
return content
|
||||||
else:
|
else:
|
||||||
|
@ -19,6 +19,8 @@ Engine using the Compute Engine metadata server.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
from google.auth import credentials
|
from google.auth import credentials
|
||||||
from google.auth import exceptions
|
from google.auth import exceptions
|
||||||
from google.auth.compute_engine import _metadata
|
from google.auth.compute_engine import _metadata
|
||||||
@ -89,8 +91,9 @@ class Credentials(credentials.ReadOnlyScoped, credentials.Credentials):
|
|||||||
self.token, self.expiry = _metadata.get_service_account_token(
|
self.token, self.expiry = _metadata.get_service_account_token(
|
||||||
request,
|
request,
|
||||||
service_account=self._service_account_email)
|
service_account=self._service_account_email)
|
||||||
except exceptions.TransportError as exc:
|
except exceptions.TransportError as caught_exc:
|
||||||
raise exceptions.RefreshError(exc)
|
new_exc = exceptions.RefreshError(caught_exc)
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def service_account_email(self):
|
def service_account_email(self):
|
||||||
|
@ -122,6 +122,43 @@ class Credentials(object):
|
|||||||
self.apply(headers)
|
self.apply(headers)
|
||||||
|
|
||||||
|
|
||||||
|
class AnonymousCredentials(Credentials):
|
||||||
|
"""Credentials that do not provide any authentication information.
|
||||||
|
|
||||||
|
These are useful in the case of services that support anonymous access or
|
||||||
|
local service emulators that do not use credentials.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def expired(self):
|
||||||
|
"""Returns `False`, anonymous credentials never expire."""
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def valid(self):
|
||||||
|
"""Returns `True`, anonymous credentials are always valid."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def refresh(self, request):
|
||||||
|
"""Raises :class:`ValueError``, anonymous credentials cannot be
|
||||||
|
refreshed."""
|
||||||
|
raise ValueError("Anonymous credentials cannot be refreshed.")
|
||||||
|
|
||||||
|
def apply(self, headers, token=None):
|
||||||
|
"""Anonymous credentials do nothing to the request.
|
||||||
|
|
||||||
|
The optional ``token`` argument is not supported.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If a token was specified.
|
||||||
|
"""
|
||||||
|
if token is not None:
|
||||||
|
raise ValueError("Anonymous credentials don't support tokens.")
|
||||||
|
|
||||||
|
def before_request(self, request, method, url, headers):
|
||||||
|
"""Anonymous credentials do nothing to the request."""
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
class ReadOnlyScoped(object):
|
class ReadOnlyScoped(object):
|
||||||
"""Interface for credentials whose scopes can be queried.
|
"""Interface for credentials whose scopes can be queried.
|
||||||
@ -136,7 +173,7 @@ class ReadOnlyScoped(object):
|
|||||||
|
|
||||||
if credentials.requires_scopes:
|
if credentials.requires_scopes:
|
||||||
# Scoping is required.
|
# Scoping is required.
|
||||||
credentials = credentials.create_scoped(['one', 'two'])
|
credentials = credentials.with_scopes(scopes=['one', 'two'])
|
||||||
|
|
||||||
Credentials that require scopes must either be constructed with scopes::
|
Credentials that require scopes must either be constructed with scopes::
|
||||||
|
|
||||||
@ -172,6 +209,9 @@ class ReadOnlyScoped(object):
|
|||||||
.. warning: This method is not guaranteed to be accurate if the
|
.. warning: This method is not guaranteed to be accurate if the
|
||||||
credentials are :attr:`~Credentials.invalid`.
|
credentials are :attr:`~Credentials.invalid`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
scopes (Sequence[str]): The list of scopes to check.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if the credentials have the given scopes.
|
bool: True if the credentials have the given scopes.
|
||||||
"""
|
"""
|
||||||
@ -211,7 +251,8 @@ class Scoped(ReadOnlyScoped):
|
|||||||
"""Create a copy of these credentials with the specified scopes.
|
"""Create a copy of these credentials with the specified scopes.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
scopes (Sequence[str]): The list of scopes to request.
|
scopes (Sequence[str]): The list of scopes to attach to the
|
||||||
|
current credentials.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
NotImplementedError: If the credentials' scopes can not be changed.
|
NotImplementedError: If the credentials' scopes can not be changed.
|
||||||
|
@ -29,7 +29,7 @@ If you're going to verify many messages with the same certificate, you can use
|
|||||||
To sign messages use :class:`RSASigner` with a private key::
|
To sign messages use :class:`RSASigner` with a private key::
|
||||||
|
|
||||||
private_key = open('private_key.pem').read()
|
private_key = open('private_key.pem').read()
|
||||||
signer = crypt.RSASigner(private_key)
|
signer = crypt.RSASigner.from_string(private_key)
|
||||||
signature = signer.sign(message)
|
signature = signer.sign(message)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ import datetime
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
import cachetools
|
import cachetools
|
||||||
|
import six
|
||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
|
|
||||||
from google.auth import _helpers
|
from google.auth import _helpers
|
||||||
@ -101,8 +102,9 @@ def _decode_jwt_segment(encoded_section):
|
|||||||
section_bytes = _helpers.padded_urlsafe_b64decode(encoded_section)
|
section_bytes = _helpers.padded_urlsafe_b64decode(encoded_section)
|
||||||
try:
|
try:
|
||||||
return json.loads(section_bytes.decode('utf-8'))
|
return json.loads(section_bytes.decode('utf-8'))
|
||||||
except ValueError:
|
except ValueError as caught_exc:
|
||||||
raise ValueError('Can\'t parse segment: {0}'.format(section_bytes))
|
new_exc = ValueError('Can\'t parse segment: {0}'.format(section_bytes))
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
|
|
||||||
|
|
||||||
def _unverified_decode(token):
|
def _unverified_decode(token):
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
|
import six
|
||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
|
|
||||||
@ -104,8 +105,9 @@ class Request(transport.Request):
|
|||||||
response = connection.getresponse()
|
response = connection.getresponse()
|
||||||
return Response(response)
|
return Response(response)
|
||||||
|
|
||||||
except (http_client.HTTPException, socket.error) as exc:
|
except (http_client.HTTPException, socket.error) as caught_exc:
|
||||||
raise exceptions.TransportError(exc)
|
new_exc = exceptions.TransportError(caught_exc)
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
connection.close()
|
connection.close()
|
||||||
|
@ -16,13 +16,17 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import six
|
||||||
try:
|
try:
|
||||||
import grpc
|
import grpc
|
||||||
except ImportError: # pragma: NO COVER
|
except ImportError as caught_exc: # pragma: NO COVER
|
||||||
raise ImportError(
|
six.raise_from(
|
||||||
'gRPC is not installed, please install the grpcio package to use the '
|
ImportError(
|
||||||
'gRPC transport.')
|
'gRPC is not installed, please install the grpcio package '
|
||||||
import six
|
'to use the gRPC transport.'
|
||||||
|
),
|
||||||
|
caught_exc,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AuthMetadataPlugin(grpc.AuthMetadataPlugin):
|
class AuthMetadataPlugin(grpc.AuthMetadataPlugin):
|
||||||
|
@ -16,15 +16,23 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import functools
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import requests
|
import requests
|
||||||
except ImportError: # pragma: NO COVER
|
except ImportError as caught_exc: # pragma: NO COVER
|
||||||
raise ImportError(
|
import six
|
||||||
'The requests library is not installed, please install the requests '
|
six.raise_from(
|
||||||
'package to use the requests transport.')
|
ImportError(
|
||||||
import requests.exceptions
|
'The requests library is not installed, please install the '
|
||||||
|
'requests package to use the requests transport.'
|
||||||
|
),
|
||||||
|
caught_exc,
|
||||||
|
)
|
||||||
|
import requests.adapters # pylint: disable=ungrouped-imports
|
||||||
|
import requests.exceptions # pylint: disable=ungrouped-imports
|
||||||
|
import six # pylint: disable=ungrouped-imports
|
||||||
|
|
||||||
from google.auth import exceptions
|
from google.auth import exceptions
|
||||||
from google.auth import transport
|
from google.auth import transport
|
||||||
@ -111,8 +119,9 @@ class Request(transport.Request):
|
|||||||
method, url, data=body, headers=headers, timeout=timeout,
|
method, url, data=body, headers=headers, timeout=timeout,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
return _Response(response)
|
return _Response(response)
|
||||||
except requests.exceptions.RequestException as exc:
|
except requests.exceptions.RequestException as caught_exc:
|
||||||
raise exceptions.TransportError(exc)
|
new_exc = exceptions.TransportError(caught_exc)
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
|
|
||||||
|
|
||||||
class AuthorizedSession(requests.Session):
|
class AuthorizedSession(requests.Session):
|
||||||
@ -139,22 +148,35 @@ class AuthorizedSession(requests.Session):
|
|||||||
retried.
|
retried.
|
||||||
max_refresh_attempts (int): The maximum number of times to attempt to
|
max_refresh_attempts (int): The maximum number of times to attempt to
|
||||||
refresh the credentials and retry the request.
|
refresh the credentials and retry the request.
|
||||||
|
refresh_timeout (Optional[int]): The timeout value in seconds for
|
||||||
|
credential refresh HTTP requests.
|
||||||
kwargs: Additional arguments passed to the :class:`requests.Session`
|
kwargs: Additional arguments passed to the :class:`requests.Session`
|
||||||
constructor.
|
constructor.
|
||||||
"""
|
"""
|
||||||
def __init__(self, credentials,
|
def __init__(self, credentials,
|
||||||
refresh_status_codes=transport.DEFAULT_REFRESH_STATUS_CODES,
|
refresh_status_codes=transport.DEFAULT_REFRESH_STATUS_CODES,
|
||||||
max_refresh_attempts=transport.DEFAULT_MAX_REFRESH_ATTEMPTS,
|
max_refresh_attempts=transport.DEFAULT_MAX_REFRESH_ATTEMPTS,
|
||||||
|
refresh_timeout=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
super(AuthorizedSession, self).__init__(**kwargs)
|
super(AuthorizedSession, self).__init__(**kwargs)
|
||||||
self.credentials = credentials
|
self.credentials = credentials
|
||||||
self._refresh_status_codes = refresh_status_codes
|
self._refresh_status_codes = refresh_status_codes
|
||||||
self._max_refresh_attempts = max_refresh_attempts
|
self._max_refresh_attempts = max_refresh_attempts
|
||||||
|
self._refresh_timeout = refresh_timeout
|
||||||
|
|
||||||
|
auth_request_session = requests.Session()
|
||||||
|
|
||||||
|
# Using an adapter to make HTTP requests robust to network errors.
|
||||||
|
# This adapter retrys HTTP requests when network errors occur
|
||||||
|
# and the requests seems safely retryable.
|
||||||
|
retry_adapter = requests.adapters.HTTPAdapter(max_retries=3)
|
||||||
|
auth_request_session.mount("https://", retry_adapter)
|
||||||
|
|
||||||
# Request instance used by internal methods (for example,
|
# Request instance used by internal methods (for example,
|
||||||
# credentials.refresh).
|
# credentials.refresh).
|
||||||
# Do not pass `self` as the session here, as it can lead to infinite
|
# Do not pass `self` as the session here, as it can lead to infinite
|
||||||
# recursion.
|
# recursion.
|
||||||
self._auth_request = Request()
|
self._auth_request = Request(auth_request_session)
|
||||||
|
|
||||||
def request(self, method, url, data=None, headers=None, **kwargs):
|
def request(self, method, url, data=None, headers=None, **kwargs):
|
||||||
"""Implementation of Requests' request."""
|
"""Implementation of Requests' request."""
|
||||||
@ -191,7 +213,9 @@ class AuthorizedSession(requests.Session):
|
|||||||
response.status_code, _credential_refresh_attempt + 1,
|
response.status_code, _credential_refresh_attempt + 1,
|
||||||
self._max_refresh_attempts)
|
self._max_refresh_attempts)
|
||||||
|
|
||||||
self.credentials.refresh(self._auth_request)
|
auth_request_with_timeout = functools.partial(
|
||||||
|
self._auth_request, timeout=self._refresh_timeout)
|
||||||
|
self.credentials.refresh(auth_request_with_timeout)
|
||||||
|
|
||||||
# Recurse. Pass in the original headers, not our modified set.
|
# Recurse. Pass in the original headers, not our modified set.
|
||||||
return self.request(
|
return self.request(
|
||||||
|
@ -32,11 +32,17 @@ except ImportError: # pragma: NO COVER
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import urllib3
|
import urllib3
|
||||||
except ImportError: # pragma: NO COVER
|
except ImportError as caught_exc: # pragma: NO COVER
|
||||||
raise ImportError(
|
import six
|
||||||
'The urllib3 library is not installed, please install the urllib3 '
|
six.raise_from(
|
||||||
'package to use the urllib3 transport.')
|
ImportError(
|
||||||
import urllib3.exceptions
|
'The urllib3 library is not installed, please install the '
|
||||||
|
'urllib3 package to use the urllib3 transport.'
|
||||||
|
),
|
||||||
|
caught_exc,
|
||||||
|
)
|
||||||
|
import six
|
||||||
|
import urllib3.exceptions # pylint: disable=ungrouped-imports
|
||||||
|
|
||||||
from google.auth import exceptions
|
from google.auth import exceptions
|
||||||
from google.auth import transport
|
from google.auth import transport
|
||||||
@ -126,8 +132,9 @@ class Request(transport.Request):
|
|||||||
response = self.http.request(
|
response = self.http.request(
|
||||||
method, url, body=body, headers=headers, **kwargs)
|
method, url, body=body, headers=headers, **kwargs)
|
||||||
return _Response(response)
|
return _Response(response)
|
||||||
except urllib3.exceptions.HTTPError as exc:
|
except urllib3.exceptions.HTTPError as caught_exc:
|
||||||
raise exceptions.TransportError(exc)
|
new_exc = exceptions.TransportError(caught_exc)
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
|
|
||||||
|
|
||||||
def _make_default_http():
|
def _make_default_http():
|
||||||
|
@ -26,6 +26,7 @@ For more information about the token endpoint, see
|
|||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
import six
|
||||||
from six.moves import http_client
|
from six.moves import http_client
|
||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
|
|
||||||
@ -144,9 +145,10 @@ def jwt_grant(request, token_uri, assertion):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
access_token = response_data['access_token']
|
access_token = response_data['access_token']
|
||||||
except KeyError:
|
except KeyError as caught_exc:
|
||||||
raise exceptions.RefreshError(
|
new_exc = exceptions.RefreshError(
|
||||||
'No access token in response.', response_data)
|
'No access token in response.', response_data)
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
|
|
||||||
expiry = _parse_expiry(response_data)
|
expiry = _parse_expiry(response_data)
|
||||||
|
|
||||||
@ -190,9 +192,10 @@ def refresh_grant(request, token_uri, refresh_token, client_id, client_secret):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
access_token = response_data['access_token']
|
access_token = response_data['access_token']
|
||||||
except KeyError:
|
except KeyError as caught_exc:
|
||||||
raise exceptions.RefreshError(
|
new_exc = exceptions.RefreshError(
|
||||||
'No access token in response.', response_data)
|
'No access token in response.', response_data)
|
||||||
|
six.raise_from(new_exc, caught_exc)
|
||||||
|
|
||||||
refresh_token = response_data.get('refresh_token', refresh_token)
|
refresh_token = response_data.get('refresh_token', refresh_token)
|
||||||
expiry = _parse_expiry(response_data)
|
expiry = _parse_expiry(response_data)
|
||||||
|
@ -31,12 +31,21 @@ Authorization Code grant flow.
|
|||||||
.. _rfc6749 section 4.1: https://tools.ietf.org/html/rfc6749#section-4.1
|
.. _rfc6749 section 4.1: https://tools.ietf.org/html/rfc6749#section-4.1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import io
|
||||||
|
import json
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
from google.auth import _helpers
|
from google.auth import _helpers
|
||||||
from google.auth import credentials
|
from google.auth import credentials
|
||||||
from google.oauth2 import _client
|
from google.oauth2 import _client
|
||||||
|
|
||||||
|
|
||||||
class Credentials(credentials.Scoped, credentials.Credentials):
|
# The Google OAuth 2.0 token endpoint. Used for authorized user credentials.
|
||||||
|
_GOOGLE_OAUTH2_TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token'
|
||||||
|
|
||||||
|
|
||||||
|
class Credentials(credentials.ReadOnlyScoped, credentials.Credentials):
|
||||||
"""Credentials using OAuth 2.0 access and refresh tokens."""
|
"""Credentials using OAuth 2.0 access and refresh tokens."""
|
||||||
|
|
||||||
def __init__(self, token, refresh_token=None, id_token=None,
|
def __init__(self, token, refresh_token=None, id_token=None,
|
||||||
@ -109,15 +118,6 @@ class Credentials(credentials.Scoped, credentials.Credentials):
|
|||||||
the initial token is requested and can not be changed."""
|
the initial token is requested and can not be changed."""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def with_scopes(self, scopes):
|
|
||||||
"""Unavailable, OAuth 2.0 credentials can not be re-scoped.
|
|
||||||
|
|
||||||
OAuth 2.0 credentials have their scopes set when the initial token is
|
|
||||||
requested and can not be changed.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError(
|
|
||||||
'OAuth 2.0 Credentials can not modify their scopes.')
|
|
||||||
|
|
||||||
@_helpers.copy_docstring(credentials.Credentials)
|
@_helpers.copy_docstring(credentials.Credentials)
|
||||||
def refresh(self, request):
|
def refresh(self, request):
|
||||||
access_token, refresh_token, expiry, grant_response = (
|
access_token, refresh_token, expiry, grant_response = (
|
||||||
@ -129,3 +129,56 @@ class Credentials(credentials.Scoped, credentials.Credentials):
|
|||||||
self.expiry = expiry
|
self.expiry = expiry
|
||||||
self._refresh_token = refresh_token
|
self._refresh_token = refresh_token
|
||||||
self._id_token = grant_response.get('id_token')
|
self._id_token = grant_response.get('id_token')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_authorized_user_info(cls, info, scopes=None):
|
||||||
|
"""Creates a Credentials instance from parsed authorized user info.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
info (Mapping[str, str]): The authorized user info in Google
|
||||||
|
format.
|
||||||
|
scopes (Sequence[str]): Optional list of scopes to include in the
|
||||||
|
credentials.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
google.oauth2.credentials.Credentials: The constructed
|
||||||
|
credentials.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the info is not in the expected format.
|
||||||
|
"""
|
||||||
|
keys_needed = set(('refresh_token', 'client_id', 'client_secret'))
|
||||||
|
missing = keys_needed.difference(six.iterkeys(info))
|
||||||
|
|
||||||
|
if missing:
|
||||||
|
raise ValueError(
|
||||||
|
'Authorized user info was not in the expected format, missing '
|
||||||
|
'fields {}.'.format(', '.join(missing)))
|
||||||
|
|
||||||
|
return Credentials(
|
||||||
|
None, # No access token, must be refreshed.
|
||||||
|
refresh_token=info['refresh_token'],
|
||||||
|
token_uri=_GOOGLE_OAUTH2_TOKEN_ENDPOINT,
|
||||||
|
scopes=scopes,
|
||||||
|
client_id=info['client_id'],
|
||||||
|
client_secret=info['client_secret'])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_authorized_user_file(cls, filename, scopes=None):
|
||||||
|
"""Creates a Credentials instance from an authorized user json file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename (str): The path to the authorized user json file.
|
||||||
|
scopes (Sequence[str]): Optional list of scopes to include in the
|
||||||
|
credentials.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
google.oauth2.credentials.Credentials: The constructed
|
||||||
|
credentials.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the file is not in the expected format.
|
||||||
|
"""
|
||||||
|
with io.open(filename, 'r', encoding='utf-8') as json_file:
|
||||||
|
data = json.load(json_file)
|
||||||
|
return cls.from_authorized_user_info(data, scopes)
|
||||||
|
@ -79,7 +79,7 @@ from google.auth import credentials
|
|||||||
from google.auth import jwt
|
from google.auth import jwt
|
||||||
from google.oauth2 import _client
|
from google.oauth2 import _client
|
||||||
|
|
||||||
_DEFAULT_TOKEN_LIFETIME_SECS = 3600 # 1 hour in sections
|
_DEFAULT_TOKEN_LIFETIME_SECS = 3600 # 1 hour in seconds
|
||||||
|
|
||||||
|
|
||||||
class Credentials(credentials.Signing,
|
class Credentials(credentials.Signing,
|
||||||
|
Reference in New Issue
Block a user