How to download Google Drive files to a Jupyter notebook using the Google Drive Python API?

Question:

I’m trying to download my Google Drive files to a Jupyter notebook using the Google Drive Python API. Thus, I’m following this post. But since this is outdated, I’m having problems when creating the credential using OAuth 2.0 verification.

Since Jupyter notebook opens a localhost URL, I decided to configure it as a Web Application for the Type of Application. Then, I’m not sure about what to configure on the JavaScript authoritative sources and Authorized redirect URIs fields. I guess that in the first field, I could use the local host URL when opening a Jupyter notebook. In the case of the second field, I don’t know what to put on it. The configuration was done as follows.config_image.

When running the code suggested on the Medium post:

obj = lambda: None
lmao = {"auth_host_name":'localhost', 'noauth_local_webserver':'store_true', 'auth_host_port':[8080, 8090], 'logging_level':'ERROR'}
for k, v in lmao.items():
    setattr(obj, k, v)
    
# authorization boilerplate code
SCOPES = 'https://www.googleapis.com/auth/drive.readonly'
store = file.Storage('token.json')
creds = store.get()
# The following will give you a link if token.json does not exist, the link allows the user to give this app permission
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('client_id.json', SCOPES)
    creds = tools.run_flow(flow, store, obj)

I’m getting this error: InvalidClientSecretsError: Missing property "redirect_uris" in a client type of "web", regarding to the redirect URI that I don’t know how to configure.

InvalidClientSecretsError                 Traceback (most recent call last)
Cell In [2], line 12
     10 # The following will give you a link if token.json does not exist, the link allows the user to give this app permission
     11 if not creds or creds.invalid:
---> 12     flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
     13     creds = tools.run_flow(flow, store, obj)

File ~/.pyenv/versions/py-3.10.7/lib/python3.10/site-packages/oauth2client/_helpers.py:133, in positional.<locals>.positional_decorator.<locals>.positional_wrapper(*args, **kwargs)
    131     elif positional_parameters_enforcement == POSITIONAL_WARNING:
    132         logger.warning(message)
--> 133 return wrapped(*args, **kwargs)

File ~/.pyenv/versions/py-3.10.7/lib/python3.10/site-packages/oauth2client/client.py:2134, in flow_from_clientsecrets(filename, scope, redirect_uri, message, cache, login_hint, device_uri, pkce, code_verifier, prompt)
   2097 """Create a Flow from a clientsecrets file.
   2098 
   2099 Will create the right kind of Flow based on the contents of the
   (...)
   2131                                              invalid.
   2132 """
   2133 try:
-> 2134     client_type, client_info = clientsecrets.loadfile(filename,
   2135                                                       cache=cache)
   2136     if client_type in (clientsecrets.TYPE_WEB,
   2137                        clientsecrets.TYPE_INSTALLED):
   2138         constructor_kwargs = {
   2139             'redirect_uri': redirect_uri,
   2140             'auth_uri': client_info['auth_uri'],
   2141             'token_uri': client_info['token_uri'],
   2142             'login_hint': login_hint,
   2143         }

File ~/.pyenv/versions/py-3.10.7/lib/python3.10/site-packages/oauth2client/clientsecrets.py:165, in loadfile(filename, cache)
    162 _SECRET_NAMESPACE = 'oauth2client:secrets#ns'
    164 if not cache:
--> 165     return _loadfile(filename)
    167 obj = cache.get(filename, namespace=_SECRET_NAMESPACE)
    168 if obj is None:

File ~/.pyenv/versions/py-3.10.7/lib/python3.10/site-packages/oauth2client/clientsecrets.py:126, in _loadfile(filename)
    123 except IOError as exc:
    124     raise InvalidClientSecretsError('Error opening file', exc.filename,
    125                                     exc.strerror, exc.errno)
--> 126 return _validate_clientsecrets(obj)

File ~/.pyenv/versions/py-3.10.7/lib/python3.10/site-packages/oauth2client/clientsecrets.py:99, in _validate_clientsecrets(clientsecrets_dict)
     97 for prop_name in VALID_CLIENT[client_type]['required']:
     98     if prop_name not in client_info:
---> 99         raise InvalidClientSecretsError(
    100             'Missing property "{0}" in a client type of "{1}".'.format(
    101                 prop_name, client_type))
    102 for prop_name in VALID_CLIENT[client_type]['string']:
    103     if client_info[prop_name].startswith('[['):

InvalidClientSecretsError: Missing property "redirect_uris" in a client type of "web".

Can someone tell me how to configure a credential on Google Drive API for accessing my Google Drive files with Jupyter notebooks?

I really appreciate any help you can provide.

Asked By: 0x55b1E06FF

||

Answers:

Checking the documentation of Jupyter here the Authorized JavaScript origins should be set to to your hub’s public address, and the Authorized redirect URIs should be set to the same but followed by /hub/oauth_callback.

So if your hub’s public address is http://localhost:8890 then your redirect URI should be http://localhost:8890/hub/oauth_callback.

If that doesn’t work it will be better to contact their support line and request for that information.

Answered By: Giselle Valladares

I realized that to access Google Drive files with a Jupyter notebook, it needs to be configured as a Desktop Application in the Type of Application field as follows:

desktop app

Another aspect to take care of is specifying the correct ports in the code I provided:

lmao = {"auth_host_name":'localhost', 'noauth_local_webserver':'store_true', 'auth_host_port':[8890, 8891], 'logging_level':'ERROR'}

A last caveat is to configure the Test users field on the OAuth consent screen tab and add the email with which we are accessing the Drive, as follows:

OAuth config

If you need to download not only files but also folders from your Google Drive, you can use this code.

Answered By: 0x55b1E06FF