1
- """Private module for fetching Google BigQuery credentials."""
1
+ """Private module for fetching Google API credentials."""
2
2
3
3
import json
4
4
import logging
5
5
import os
6
6
import os .path
7
7
8
- import pydata_google_auth .exceptions
8
+ import google .auth
9
+ import google .auth .exceptions
10
+ import google .oauth2 .credentials
11
+ from google_auth_oauthlib import flow
12
+ import oauthlib .oauth2 .rfc6749 .errors
13
+ import google .auth .transport .requests
9
14
15
+ from pydata_google_auth import exceptions
10
16
11
- logger = logging .getLogger (__name__ )
12
17
18
+ logger = logging .getLogger (__name__ )
13
19
14
- def default (
15
- scopes ,
16
- client_id ,
17
- client_secret ,
18
- credentials_dirname ,
19
- credentials_filename ,
20
- project_id = None ,
21
- auth_local_webserver = False ,
22
- try_credentials = None ):
23
- if try_credentials is None :
24
- def try_credentials (credentials , project_id ):
25
- return credentials , project_id
26
-
27
- return get_credentials (
28
- scopes ,
29
- client_id ,
30
- client_secret ,
31
- credentials_dirname ,
32
- credentials_filename ,
33
- project_id = project_id ,
34
- auth_local_webserver = auth_local_webserver ,
35
- try_credentials = try_credentials )
20
+ CLIENT_ID = (
21
+ '262006177488-3425ks60hkk80fssi9vpohv88g6q1iqd'
22
+ '.apps.googleusercontent.com'
23
+ )
24
+ CLIENT_SECRET = 'JSF-iczmzEgbTR-XK-2xaWAc'
25
+ CREDENTIALS_DIRNAME = 'pydata'
26
+ CREDENTIALS_FILENAME = 'pydata_google_credentials.json'
36
27
37
28
38
- def get_credentials (
29
+ def default (
39
30
scopes ,
40
- client_id ,
41
- client_secret ,
42
- credentials_dirname ,
43
- credentials_filename ,
44
- try_credentials ,
45
- project_id = None , reauth = False ,
31
+ client_id = CLIENT_ID ,
32
+ client_secret = CLIENT_SECRET ,
33
+ credentials_dirname = CREDENTIALS_DIRNAME ,
34
+ credentials_filename = CREDENTIALS_FILENAME ,
35
+ reauth = False ,
46
36
auth_local_webserver = False ):
47
37
# Try to retrieve Application Default Credentials
48
- credentials , default_project = get_application_default_credentials (
49
- scopes , project_id = project_id , try_credentials = try_credentials )
38
+ credentials , default_project = get_application_default_credentials (scopes )
50
39
51
- if credentials :
40
+ if credentials and credentials . valid :
52
41
return credentials , default_project
53
42
54
- credentials = get_user_account_credentials (
43
+ credentials = get_user_credentials (
55
44
scopes ,
56
- client_id ,
57
- client_secret ,
58
- credentials_dirname ,
59
- credentials_filename ,
60
- project_id = project_id ,
45
+ client_id = client_id ,
46
+ client_secret = client_secret ,
47
+ credentials_dirname = credentials_dirname ,
48
+ credentials_filename = credentials_filename ,
61
49
reauth = reauth ,
62
- auth_local_webserver = auth_local_webserver ,
63
- try_credentials = try_credentials )
64
- return credentials , project_id
50
+ auth_local_webserver = auth_local_webserver )
65
51
52
+ if not credentials or not credentials .valid :
53
+ raise exceptions .PyDataCredentialsError (
54
+ 'Could not get any valid credentials.' )
66
55
67
- def get_application_default_credentials (
68
- scopes , try_credentials , project_id = None ):
56
+ return credentials , None
57
+
58
+
59
+ def get_application_default_credentials (scopes ):
69
60
"""
70
61
This method tries to retrieve the "default application credentials".
71
62
This could be useful for running code on Google Cloud Platform.
@@ -85,29 +76,28 @@ def get_application_default_credentials(
85
76
from the environment. Or, the retrieved credentials do not
86
77
have access to the project (project_id) on BigQuery.
87
78
"""
88
- import google .auth
89
- from google .auth .exceptions import DefaultCredentialsError
90
79
91
80
try :
92
- credentials , default_project = google .auth .default (scopes = scopes )
93
- except (DefaultCredentialsError , IOError ):
81
+ credentials , project = google .auth .default (scopes = scopes )
82
+ except (google .auth .exceptions .DefaultCredentialsError , IOError ) as exc :
83
+ logger .debug ('Error getting default credentials: {}' .format (str (exc )))
94
84
return None , None
95
85
96
- # Even though we now have credentials, check that the credentials can be
97
- # used with BigQuery. For example, we could be running on a GCE instance
98
- # that does not allow the BigQuery scopes.
99
- billing_project = project_id or default_project
100
- return try_credentials ( credentials , billing_project )
86
+ if credentials and not credentials . valid :
87
+ request = google . auth . transport . requests . Request ()
88
+ credentials . refresh ( request )
89
+
90
+ return credentials , project
101
91
102
92
103
- def get_user_account_credentials (
93
+ def get_user_credentials (
104
94
scopes ,
105
- client_id ,
106
- client_secret ,
107
- credentials_dirname ,
108
- credentials_filename ,
109
- project_id = None , reauth = False , auth_local_webserver = False ,
110
- credentials_path = None ):
95
+ client_id = CLIENT_ID ,
96
+ client_secret = CLIENT_SECRET ,
97
+ credentials_dirname = CREDENTIALS_DIRNAME ,
98
+ credentials_filename = CREDENTIALS_FILENAME ,
99
+ reauth = False ,
100
+ auth_local_webserver = False ):
111
101
"""Gets user account credentials.
112
102
113
103
This method authenticates using user credentials, either loading saved
@@ -122,26 +112,16 @@ def get_user_account_credentials(
122
112
GoogleCredentials : credentials
123
113
Credentials for the user with BigQuery access.
124
114
"""
125
- from google_auth_oauthlib .flow import InstalledAppFlow
126
- from oauthlib .oauth2 .rfc6749 .errors import OAuth2Error
127
-
128
115
# Use the default credentials location under ~/.config and the
129
116
# equivalent directory on windows if the user has not specified a
130
117
# credentials path.
131
- if not credentials_path :
132
- credentials_path = get_default_credentials_path (
133
- credentials_dirname ,
134
- credentials_filename )
135
-
136
- # Previously, pandas-gbq saved user account credentials in the
137
- # current working directory. If the bigquery_credentials.dat file
138
- # exists in the current working directory, move the credentials to
139
- # the new default location.
140
- if os .path .isfile ('bigquery_credentials.dat' ):
141
- os .rename (credentials_filename , credentials_path )
118
+ credentials_path = get_default_credentials_path (
119
+ credentials_dirname ,
120
+ credentials_filename )
142
121
143
- credentials = load_user_account_credentials (
144
- project_id = project_id , credentials_path = credentials_path )
122
+ credentials = None
123
+ if not reauth :
124
+ credentials = load_user_credentials_from_file (credentials_path )
145
125
146
126
client_config = {
147
127
'installed' : {
@@ -153,26 +133,40 @@ def get_user_account_credentials(
153
133
}
154
134
}
155
135
156
- if credentials is None or reauth :
157
- app_flow = InstalledAppFlow .from_client_config (
136
+ if credentials is None :
137
+ app_flow = flow . InstalledAppFlow .from_client_config (
158
138
client_config , scopes = scopes )
159
139
160
140
try :
161
141
if auth_local_webserver :
162
142
credentials = app_flow .run_local_server ()
163
143
else :
164
144
credentials = app_flow .run_console ()
165
- except OAuth2Error as ex :
166
- raise pydata_google_auth . exceptions .AccessDenied (
167
- "Unable to get valid credentials: {0}" .format (ex ))
145
+ except oauthlib . oauth2 . rfc6749 . errors . OAuth2Error as exc :
146
+ raise exceptions .PyDataCredentialsError (
147
+ "Unable to get valid credentials: {0}" .format (exc ))
168
148
169
149
save_user_account_credentials (credentials , credentials_path )
170
150
151
+ if credentials and not credentials .valid :
152
+ request = google .auth .transport .requests .Request ()
153
+ credentials .refresh (request )
154
+
171
155
return credentials
172
156
173
157
174
- def load_user_account_credentials (
175
- try_credentials , project_id = None , credentials_path = None ):
158
+ def load_user_credentials_from_info (credentials_json ):
159
+ return google .oauth2 .credentials .Credentials (
160
+ token = credentials_json .get ('access_token' ),
161
+ refresh_token = credentials_json .get ('refresh_token' ),
162
+ id_token = credentials_json .get ('id_token' ),
163
+ token_uri = credentials_json .get ('token_uri' ),
164
+ client_id = credentials_json .get ('client_id' ),
165
+ client_secret = credentials_json .get ('client_secret' ),
166
+ scopes = credentials_json .get ('scopes' ))
167
+
168
+
169
+ def load_user_credentials_from_file (credentials_path ):
176
170
"""
177
171
Loads user account credentials from a local file.
178
172
@@ -192,40 +186,26 @@ def load_user_account_credentials(
192
186
credentials do not have access to the project (project_id)
193
187
on BigQuery.
194
188
"""
195
- import google .auth .transport .requests
196
- from google .oauth2 .credentials import Credentials
197
-
198
189
try :
199
190
with open (credentials_path ) as credentials_file :
200
191
credentials_json = json .load (credentials_file )
201
- except (IOError , ValueError ):
192
+ except (IOError , ValueError ) as exc :
193
+ logger .debug ('Error loading credentials from {}: {}' .format (
194
+ credentials_path , str (exc )))
202
195
return None
203
196
204
- credentials = Credentials (
205
- token = credentials_json .get ('access_token' ),
206
- refresh_token = credentials_json .get ('refresh_token' ),
207
- id_token = credentials_json .get ('id_token' ),
208
- token_uri = credentials_json .get ('token_uri' ),
209
- client_id = credentials_json .get ('client_id' ),
210
- client_secret = credentials_json .get ('client_secret' ),
211
- scopes = credentials_json .get ('scopes' ))
212
-
213
- # Refresh the token before trying to use it.
214
- request = google .auth .transport .requests .Request ()
215
- credentials .refresh (request )
216
-
217
- return try_credentials (credentials , project_id )
197
+ return load_user_credentials_from_info (credentials_json )
218
198
219
199
220
200
def get_default_credentials_path (credentials_dirname , credentials_filename ):
221
201
"""
222
- Gets the default path to the BigQuery credentials
202
+ Gets the default path to the Google user credentials
223
203
224
204
.. versionadded 0.3.0
225
205
226
206
Returns
227
207
-------
228
- Path to the BigQuery credentials
208
+ Path to the Google user credentials
229
209
"""
230
210
if os .name == 'nt' :
231
211
config_path = os .environ ['APPDATA' ]
@@ -234,7 +214,7 @@ def get_default_credentials_path(credentials_dirname, credentials_filename):
234
214
235
215
config_path = os .path .join (config_path , credentials_dirname )
236
216
237
- # Create a pandas_gbq directory in an application-specific hidden
217
+ # Create a pydata directory in an application-specific hidden
238
218
# user folder on the operating system.
239
219
if not os .path .exists (config_path ):
240
220
os .makedirs (config_path )
0 commit comments