# 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 credentials_from_file(filename, scopes=None, quota_project_id=None): """Returns credentials loaded from a file.""" if HAS_GOOGLE_AUTH: credentials, _ = google.auth.load_credentials_from_file(filename, scopes=scopes, quota_project_id=quota_project_id) return credentials else: raise EnvironmentError( "client_options.credentials_file is only supported in google-auth.") def default_credentials(scopes=None, quota_project_id=None): """Returns Application Default Credentials.""" if HAS_GOOGLE_AUTH: credentials, _ = google.auth.default(scopes=scopes, quota_project_id=quota_project_id) return credentials elif HAS_OAUTH2CLIENT: if scopes is not None or quota_project_id is not None: raise EnvironmentError( "client_options.scopes and client_options.quota_project_id are not supported in oauth2client." "Please install google-auth." ) 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