blob: d045fc147d10b334fbafed01da9f60497f449964 [file] [log] [blame]
Jon Wayne Parrott85c2c6d2017-01-05 12:34:49 -08001# 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
Jon Wayne Parrottd3a5cf42017-06-19 17:55:04 -070017import httplib2
18
Jon Wayne Parrott85c2c6d2017-01-05 12:34:49 -080019try:
20 import google.auth
Wilson Lian09527302017-01-11 14:38:18 -080021 import google.auth.credentials
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070022
Jon Wayne Parrott85c2c6d2017-01-05 12:34:49 -080023 HAS_GOOGLE_AUTH = True
24except ImportError: # pragma: NO COVER
25 HAS_GOOGLE_AUTH = False
26
27try:
Jon Wayne Parrott401e8862017-09-19 18:36:35 -070028 import google_auth_httplib2
29except ImportError: # pragma: NO COVER
30 google_auth_httplib2 = None
31
32try:
Jon Wayne Parrott85c2c6d2017-01-05 12:34:49 -080033 import oauth2client
34 import oauth2client.client
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070035
Jon Wayne Parrott85c2c6d2017-01-05 12:34:49 -080036 HAS_OAUTH2CLIENT = True
37except ImportError: # pragma: NO COVER
38 HAS_OAUTH2CLIENT = False
39
40
Bu Sun Kim790e7022020-09-11 20:18:06 -060041def credentials_from_file(filename, scopes=None, quota_project_id=None):
42 """Returns credentials loaded from a file."""
43 if HAS_GOOGLE_AUTH:
44 credentials, _ = google.auth.load_credentials_from_file(filename, scopes=scopes, quota_project_id=quota_project_id)
45 return credentials
46 else:
47 raise EnvironmentError(
48 "client_options.credentials_file is only supported in google-auth.")
49
50
51def default_credentials(scopes=None, quota_project_id=None):
Jon Wayne Parrott85c2c6d2017-01-05 12:34:49 -080052 """Returns Application Default Credentials."""
53 if HAS_GOOGLE_AUTH:
Bu Sun Kim790e7022020-09-11 20:18:06 -060054 credentials, _ = google.auth.default(scopes=scopes, quota_project_id=quota_project_id)
Jon Wayne Parrott85c2c6d2017-01-05 12:34:49 -080055 return credentials
56 elif HAS_OAUTH2CLIENT:
Bu Sun Kim790e7022020-09-11 20:18:06 -060057 if scopes is not None or quota_project_id is not None:
58 raise EnvironmentError(
59 "client_options.scopes and client_options.quota_project_id are not supported in oauth2client."
60 "Please install google-auth."
61 )
Jon Wayne Parrott85c2c6d2017-01-05 12:34:49 -080062 return oauth2client.client.GoogleCredentials.get_application_default()
63 else:
64 raise EnvironmentError(
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070065 "No authentication library is available. Please install either "
66 "google-auth or oauth2client."
67 )
Jon Wayne Parrott85c2c6d2017-01-05 12:34:49 -080068
69
70def with_scopes(credentials, scopes):
71 """Scopes the credentials if necessary.
72
73 Args:
74 credentials (Union[
75 google.auth.credentials.Credentials,
76 oauth2client.client.Credentials]): The credentials to scope.
77 scopes (Sequence[str]): The list of scopes.
78
79 Returns:
80 Union[google.auth.credentials.Credentials,
81 oauth2client.client.Credentials]: The scoped credentials.
82 """
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070083 if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
84 return google.auth.credentials.with_scopes_if_required(credentials, scopes)
Jon Wayne Parrott85c2c6d2017-01-05 12:34:49 -080085 else:
86 try:
87 if credentials.create_scoped_required():
88 return credentials.create_scoped(scopes)
89 else:
90 return credentials
91 except AttributeError:
92 return credentials
93
94
95def authorized_http(credentials):
96 """Returns an http client that is authorized with the given credentials.
97
98 Args:
99 credentials (Union[
100 google.auth.credentials.Credentials,
101 oauth2client.client.Credentials]): The credentials to use.
102
103 Returns:
104 Union[httplib2.Http, google_auth_httplib2.AuthorizedHttp]: An
105 authorized http client.
106 """
Jon Wayne Parrottd3a5cf42017-06-19 17:55:04 -0700107 from googleapiclient.http import build_http
108
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700109 if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
Jon Wayne Parrott401e8862017-09-19 18:36:35 -0700110 if google_auth_httplib2 is None:
111 raise ValueError(
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700112 "Credentials from google.auth specified, but "
113 "google-api-python-client is unable to use these credentials "
114 "unless google-auth-httplib2 is installed. Please install "
115 "google-auth-httplib2."
116 )
117 return google_auth_httplib2.AuthorizedHttp(credentials, http=build_http())
Jon Wayne Parrott85c2c6d2017-01-05 12:34:49 -0800118 else:
Igor Maravić22435292017-01-19 22:28:22 +0100119 return credentials.authorize(build_http())
Jon Wayne Parrottd3a5cf42017-06-19 17:55:04 -0700120
121
122def refresh_credentials(credentials):
123 # Refresh must use a new http instance, as the one associated with the
124 # credentials could be a AuthorizedHttp or an oauth2client-decorated
125 # Http instance which would cause a weird recursive loop of refreshing
126 # and likely tear a hole in spacetime.
127 refresh_http = httplib2.Http()
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700128 if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
Jon Wayne Parrottd3a5cf42017-06-19 17:55:04 -0700129 request = google_auth_httplib2.Request(refresh_http)
130 return credentials.refresh(request)
131 else:
132 return credentials.refresh(refresh_http)
133
134
135def apply_credentials(credentials, headers):
136 # oauth2client and google-auth have the same interface for this.
Jon Wayne Parrott20e61352018-01-18 09:16:37 -0800137 if not is_valid(credentials):
138 refresh_credentials(credentials)
Jon Wayne Parrottd3a5cf42017-06-19 17:55:04 -0700139 return credentials.apply(headers)
140
141
142def is_valid(credentials):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700143 if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
Jon Wayne Parrottd3a5cf42017-06-19 17:55:04 -0700144 return credentials.valid
145 else:
Jon Wayne Parrott20e61352018-01-18 09:16:37 -0800146 return (
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700147 credentials.access_token is not None
148 and not credentials.access_token_expired
149 )
Jon Wayne Parrottd3a5cf42017-06-19 17:55:04 -0700150
151
152def get_credentials_from_http(http):
153 if http is None:
154 return None
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700155 elif hasattr(http.request, "credentials"):
Jon Wayne Parrottd3a5cf42017-06-19 17:55:04 -0700156 return http.request.credentials
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700157 elif hasattr(http, "credentials") and not isinstance(
158 http.credentials, httplib2.Credentials
159 ):
Jon Wayne Parrottd3a5cf42017-06-19 17:55:04 -0700160 return http.credentials
161 else:
162 return None