Skip to content

Commit f7068fa

Browse files
committed
auth: add dictionary storage
Allows not to save anything to disk, which is useful overall but especially useful when working with env vars, which could be sensitive so saving their value to disk is undesirable.
1 parent 3940d7b commit f7068fa

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

pydrive2/auth.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from oauth2client.client import AccessTokenRefreshError
1111
from oauth2client.client import OAuth2WebServerFlow
1212
from oauth2client.client import OOB_CALLBACK_URN
13+
from oauth2client.contrib.dictionary_storage import DictionaryStorage
1314
from oauth2client.file import Storage
1415
from oauth2client.tools import ClientRedirectHandler
1516
from oauth2client.tools import ClientRedirectServer
@@ -197,9 +198,9 @@ def __init__(
197198
self.settings = settings or self.DEFAULT_SETTINGS
198199
ValidateSettings(self.settings)
199200

200-
self._storages = self._InitializeStoragesFromSettings()
201-
# Only one (`file`) backend is supported now
202-
self._default_storage = self._storages["file"]
201+
storages, default = self._InitializeStoragesFromSettings()
202+
self._storages = storages
203+
self._default_storage = default
203204

204205
@property
205206
def access_token_expired(self):
@@ -337,7 +338,7 @@ def ServiceAuth(self):
337338
)
338339

339340
def _InitializeStoragesFromSettings(self):
340-
result = {"file": None}
341+
result = {"file": None, "dictionary": None}
341342
backend = self.settings.get("save_credentials_backend")
342343
save_credentials = self.settings.get("save_credentials")
343344
if backend == "file":
@@ -347,11 +348,16 @@ def _InitializeStoragesFromSettings(self):
347348
"Please specify credentials file to read"
348349
)
349350
result[backend] = Storage(credentials_file)
351+
elif backend == "dictionary":
352+
result[backend] = DictionaryStorage(
353+
self.settings["save_credentials_dict"],
354+
self.settings["save_credentials_key"],
355+
)
350356
elif save_credentials:
351357
raise InvalidConfigError(
352358
"Unknown save_credentials_backend: %s" % backend
353359
)
354-
return result
360+
return result, result.get(backend)
355361

356362
def LoadCredentials(self, backend=None):
357363
"""Loads credentials or create empty credentials if it doesn't exist.
@@ -366,6 +372,8 @@ def LoadCredentials(self, backend=None):
366372
raise InvalidConfigError("Please specify credential backend")
367373
if backend == "file":
368374
self.LoadCredentialsFile()
375+
elif backend == "dictionary":
376+
self._LoadCredentialsDictionary()
369377
else:
370378
raise InvalidConfigError("Unknown save_credentials_backend")
371379

@@ -399,6 +407,10 @@ def LoadCredentialsFile(self, credentials_file=None):
399407
if self.credentials:
400408
self.credentials.set_store(self._default_storage)
401409

410+
def _LoadCredentialsDictionary(self):
411+
self._default_storage = self._storages["dictionary"]
412+
self.credentials = self._default_storage.get()
413+
402414
def SaveCredentials(self, backend=None):
403415
"""Saves credentials according to specified backend.
404416
@@ -415,6 +427,8 @@ def SaveCredentials(self, backend=None):
415427
raise InvalidConfigError("Please specify credential backend")
416428
if backend == "file":
417429
self.SaveCredentialsFile()
430+
elif backend == "dictionary":
431+
self._SaveCredentialsDictionary()
418432
else:
419433
raise InvalidConfigError("Unknown save_credentials_backend")
420434

@@ -446,6 +460,13 @@ def SaveCredentialsFile(self, credentials_file=None):
446460
"Credentials file cannot be symbolic link"
447461
)
448462

463+
def _SaveCredentialsDictionary(self):
464+
if self.credentials is None:
465+
raise InvalidCredentialsError("No credentials to save")
466+
467+
storage = self._storages["dictionary"]
468+
storage.put(self.credentials)
469+
449470
def LoadClientConfig(self, backend=None):
450471
"""Loads client configuration according to specified backend.
451472

pydrive2/test/test_oauth.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,33 @@ def test_09_SaveLoadCredentialsUsesDefaultStorage(mocker):
125125
assert spy.call_count == 0
126126

127127

128+
def test_10_LocalWebServerAuthFromSavedCredentialsDictionary():
129+
creds_dict = {}
130+
settings = {
131+
"client_config_backend": "settings",
132+
"client_config": {
133+
"client_id": "47794215776-cd9ssb6a4vv5otkq6n0iadpgc4efgjb1.apps.googleusercontent.com", # noqa: E501
134+
"client_secret": "i2gerGA7uBjZbR08HqSOSt9Z",
135+
},
136+
"oauth_scope": ["https://www.googleapis.com/auth/drive"],
137+
"save_credentials": True,
138+
"save_credentials_backend": "dictionary",
139+
"save_credentials_dict": creds_dict,
140+
"save_credentials_key": "creds",
141+
}
142+
ga = GoogleAuth(settings=settings)
143+
ga.ServiceAuth()
144+
assert creds_dict
145+
creds_dict_copy = creds_dict.copy()
146+
# Secondary auth should be made only using the previously saved
147+
# login info
148+
ga = GoogleAuth(settings=settings)
149+
ga.LocalWebserverAuth()
150+
assert creds_dict == creds_dict_copy
151+
assert not ga.access_token_expired
152+
time.sleep(1)
153+
154+
128155
def CheckCredentialsFile(credentials, no_file=False):
129156
ga = GoogleAuth(settings_file_path("test_oauth_default.yaml"))
130157
ga.LoadCredentialsFile(credentials)

0 commit comments

Comments
 (0)