1# Copyright 2016 Google Inc. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Helpers for authentication using oauth2client or google-auth.""" 16 17import httplib2 18 19try: 20 import google.auth 21 import google.auth.credentials 22 HAS_GOOGLE_AUTH = True 23except ImportError: # pragma: NO COVER 24 HAS_GOOGLE_AUTH = False 25 26try: 27 import google_auth_httplib2 28except ImportError: # pragma: NO COVER 29 google_auth_httplib2 = None 30 31try: 32 import oauth2client 33 import oauth2client.client 34 HAS_OAUTH2CLIENT = True 35except ImportError: # pragma: NO COVER 36 HAS_OAUTH2CLIENT = False 37 38 39def default_credentials(): 40 """Returns Application Default Credentials.""" 41 if HAS_GOOGLE_AUTH: 42 credentials, _ = google.auth.default() 43 return credentials 44 elif HAS_OAUTH2CLIENT: 45 return oauth2client.client.GoogleCredentials.get_application_default() 46 else: 47 raise EnvironmentError( 48 'No authentication library is available. Please install either ' 49 'google-auth or oauth2client.') 50 51 52def with_scopes(credentials, scopes): 53 """Scopes the credentials if necessary. 54 55 Args: 56 credentials (Union[ 57 google.auth.credentials.Credentials, 58 oauth2client.client.Credentials]): The credentials to scope. 59 scopes (Sequence[str]): The list of scopes. 60 61 Returns: 62 Union[google.auth.credentials.Credentials, 63 oauth2client.client.Credentials]: The scoped credentials. 64 """ 65 if HAS_GOOGLE_AUTH and isinstance( 66 credentials, google.auth.credentials.Credentials): 67 return google.auth.credentials.with_scopes_if_required( 68 credentials, scopes) 69 else: 70 try: 71 if credentials.create_scoped_required(): 72 return credentials.create_scoped(scopes) 73 else: 74 return credentials 75 except AttributeError: 76 return credentials 77 78 79def authorized_http(credentials): 80 """Returns an http client that is authorized with the given credentials. 81 82 Args: 83 credentials (Union[ 84 google.auth.credentials.Credentials, 85 oauth2client.client.Credentials]): The credentials to use. 86 87 Returns: 88 Union[httplib2.Http, google_auth_httplib2.AuthorizedHttp]: An 89 authorized http client. 90 """ 91 from googleapiclient.http import build_http 92 93 if HAS_GOOGLE_AUTH and isinstance( 94 credentials, google.auth.credentials.Credentials): 95 if google_auth_httplib2 is None: 96 raise ValueError( 97 'Credentials from google.auth specified, but ' 98 'google-api-python-client is unable to use these credentials ' 99 'unless google-auth-httplib2 is installed. Please install ' 100 'google-auth-httplib2.') 101 return google_auth_httplib2.AuthorizedHttp(credentials, 102 http=build_http()) 103 else: 104 return credentials.authorize(build_http()) 105 106 107def refresh_credentials(credentials): 108 # Refresh must use a new http instance, as the one associated with the 109 # credentials could be a AuthorizedHttp or an oauth2client-decorated 110 # Http instance which would cause a weird recursive loop of refreshing 111 # and likely tear a hole in spacetime. 112 refresh_http = httplib2.Http() 113 if HAS_GOOGLE_AUTH and isinstance( 114 credentials, google.auth.credentials.Credentials): 115 request = google_auth_httplib2.Request(refresh_http) 116 return credentials.refresh(request) 117 else: 118 return credentials.refresh(refresh_http) 119 120 121def apply_credentials(credentials, headers): 122 # oauth2client and google-auth have the same interface for this. 123 if not is_valid(credentials): 124 refresh_credentials(credentials) 125 return credentials.apply(headers) 126 127 128def is_valid(credentials): 129 if HAS_GOOGLE_AUTH and isinstance( 130 credentials, google.auth.credentials.Credentials): 131 return credentials.valid 132 else: 133 return ( 134 credentials.access_token is not None and 135 not credentials.access_token_expired) 136 137 138def get_credentials_from_http(http): 139 if http is None: 140 return None 141 elif hasattr(http.request, 'credentials'): 142 return http.request.credentials 143 elif (hasattr(http, 'credentials') 144 and not isinstance(http.credentials, httplib2.Credentials)): 145 return http.credentials 146 else: 147 return None 148