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 23 HAS_GOOGLE_AUTH = True 24except ImportError: # pragma: NO COVER 25 HAS_GOOGLE_AUTH = False 26 27try: 28 import google_auth_httplib2 29except ImportError: # pragma: NO COVER 30 google_auth_httplib2 = None 31 32try: 33 import oauth2client 34 import oauth2client.client 35 36 HAS_OAUTH2CLIENT = True 37except ImportError: # pragma: NO COVER 38 HAS_OAUTH2CLIENT = False 39 40 41def default_credentials(): 42 """Returns Application Default Credentials.""" 43 if HAS_GOOGLE_AUTH: 44 credentials, _ = google.auth.default() 45 return credentials 46 elif HAS_OAUTH2CLIENT: 47 return oauth2client.client.GoogleCredentials.get_application_default() 48 else: 49 raise EnvironmentError( 50 "No authentication library is available. Please install either " 51 "google-auth or oauth2client." 52 ) 53 54 55def with_scopes(credentials, scopes): 56 """Scopes the credentials if necessary. 57 58 Args: 59 credentials (Union[ 60 google.auth.credentials.Credentials, 61 oauth2client.client.Credentials]): The credentials to scope. 62 scopes (Sequence[str]): The list of scopes. 63 64 Returns: 65 Union[google.auth.credentials.Credentials, 66 oauth2client.client.Credentials]: The scoped credentials. 67 """ 68 if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials): 69 return google.auth.credentials.with_scopes_if_required(credentials, scopes) 70 else: 71 try: 72 if credentials.create_scoped_required(): 73 return credentials.create_scoped(scopes) 74 else: 75 return credentials 76 except AttributeError: 77 return credentials 78 79 80def authorized_http(credentials): 81 """Returns an http client that is authorized with the given credentials. 82 83 Args: 84 credentials (Union[ 85 google.auth.credentials.Credentials, 86 oauth2client.client.Credentials]): The credentials to use. 87 88 Returns: 89 Union[httplib2.Http, google_auth_httplib2.AuthorizedHttp]: An 90 authorized http client. 91 """ 92 from googleapiclient.http import build_http 93 94 if HAS_GOOGLE_AUTH and isinstance(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 ) 102 return google_auth_httplib2.AuthorizedHttp(credentials, 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(credentials, google.auth.credentials.Credentials): 114 request = google_auth_httplib2.Request(refresh_http) 115 return credentials.refresh(request) 116 else: 117 return credentials.refresh(refresh_http) 118 119 120def apply_credentials(credentials, headers): 121 # oauth2client and google-auth have the same interface for this. 122 if not is_valid(credentials): 123 refresh_credentials(credentials) 124 return credentials.apply(headers) 125 126 127def is_valid(credentials): 128 if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials): 129 return credentials.valid 130 else: 131 return ( 132 credentials.access_token is not None 133 and not credentials.access_token_expired 134 ) 135 136 137def get_credentials_from_http(http): 138 if http is None: 139 return None 140 elif hasattr(http.request, "credentials"): 141 return http.request.credentials 142 elif hasattr(http, "credentials") and not isinstance( 143 http.credentials, httplib2.Credentials 144 ): 145 return http.credentials 146 else: 147 return None 148