# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Helpers for authentication using oauth2client or google-auth."""
import httplib2
try:
import google.auth
import google.auth.credentials
HAS_GOOGLE_AUTH = True
except ImportError: # pragma: NO COVER
HAS_GOOGLE_AUTH = False
try:
import google_auth_httplib2
except ImportError: # pragma: NO COVER
google_auth_httplib2 = None
try:
import oauth2client
import oauth2client.client
HAS_OAUTH2CLIENT = True
except ImportError: # pragma: NO COVER
HAS_OAUTH2CLIENT = False
def default_credentials():
"""Returns Application Default Credentials."""
if HAS_GOOGLE_AUTH:
credentials, _ = google.auth.default()
return credentials
elif HAS_OAUTH2CLIENT:
return oauth2client.client.GoogleCredentials.get_application_default()
else:
raise EnvironmentError(
'No authentication library is available. Please install either '
'google-auth or oauth2client.')
def with_scopes(credentials, scopes):
"""Scopes the credentials if necessary.
Args:
credentials (Union[
google.auth.credentials.Credentials,
oauth2client.client.Credentials]): The credentials to scope.
scopes (Sequence[str]): The list of scopes.
Returns:
Union[google.auth.credentials.Credentials,
oauth2client.client.Credentials]: The scoped credentials.
"""
if HAS_GOOGLE_AUTH and isinstance(
credentials, google.auth.credentials.Credentials):
return google.auth.credentials.with_scopes_if_required(
credentials, scopes)
else:
try:
if credentials.create_scoped_required():
return credentials.create_scoped(scopes)
else:
return credentials
except AttributeError:
return credentials
def authorized_http(credentials):
"""Returns an http client that is authorized with the given credentials.
Args:
credentials (Union[
google.auth.credentials.Credentials,
oauth2client.client.Credentials]): The credentials to use.
Returns:
Union[httplib2.Http, google_auth_httplib2.AuthorizedHttp]: An
authorized http client.
"""
from googleapiclient.http import build_http
if HAS_GOOGLE_AUTH and isinstance(
credentials, google.auth.credentials.Credentials):
if google_auth_httplib2 is None:
raise ValueError(
'Credentials from google.auth specified, but '
'google-api-python-client is unable to use these credentials '
'unless google-auth-httplib2 is installed. Please install '
'google-auth-httplib2.')
return google_auth_httplib2.AuthorizedHttp(credentials,
http=build_http())
else:
return credentials.authorize(build_http())
def refresh_credentials(credentials):
# Refresh must use a new http instance, as the one associated with the
# credentials could be a AuthorizedHttp or an oauth2client-decorated
# Http instance which would cause a weird recursive loop of refreshing
# and likely tear a hole in spacetime.
refresh_http = httplib2.Http()
if HAS_GOOGLE_AUTH and isinstance(
credentials, google.auth.credentials.Credentials):
request = google_auth_httplib2.Request(refresh_http)
return credentials.refresh(request)
else:
return credentials.refresh(refresh_http)
def apply_credentials(credentials, headers):
# oauth2client and google-auth have the same interface for this.
if not is_valid(credentials):
refresh_credentials(credentials)
return credentials.apply(headers)
def is_valid(credentials):
if HAS_GOOGLE_AUTH and isinstance(
credentials, google.auth.credentials.Credentials):
return credentials.valid
else:
return (
credentials.access_token is not None and
not credentials.access_token_expired)
def get_credentials_from_http(http):
if http is None:
return None
elif hasattr(http.request, 'credentials'):
return http.request.credentials
elif (hasattr(http, 'credentials')
and not isinstance(http.credentials, httplib2.Credentials)):
return http.credentials
else:
return None