Around the authentication of PyDrive2, a package that operates Google Drive with Python

Introduction

In this article, we will take up PyDrive2 (GitHub) from among the packages that operate Google Drive with Python. Google Drive can be operated via Drive API, but I will summarize the authentication part of Drive API in PyDrive2 as a memorandum. Specifically, it deals with the following.

--How to create credentials (OAuth 2.0 client ID) on GCP console --How to authenticate with PyDrive2 --How to save the authentication information on the local terminal and prevent the browser authentication screen from appearing each time

About PyDrive2

PyDrive (GitHub) may be a little known as a package for operating Google Drive with Python. Unfortunately, PyDrive has been out of update for over a year now.

It seems that PyDrive2 was forked from PyDrive recently (January 2020). PyDrive2 claims to be "Maintained fork of PyDrive."

It seems that PyDrive2 hasn't incorporated any backwards incompatible changes yet (as of May 2020). As a PyDrive2 document, PyDrive Document is even linked. In addition, the knowledge accumulated in the issue of PyDrive has the impression that it can be applied as it is to PyDrive2.

Operating environment

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.6
BuildVersion:	18G3020
$ python -V
Python 3.8.1
$ pip list | grep PyDrive2
PyDrive2                 1.4.10

Start using PyDrive2

Follow the PyDrive documentation Quickstart (https://gsuitedevs.github.io/PyDrive/docs/build/html/quickstart.html).

  1. Create the credentials required to operate the Drive API in the GCP console
  2. Authentication using the created authentication information

Proceed in the order of.

1. Create credentials from the GCP console

It is assumed that you have a GCP (Google Cloud Platform) account and have one or more projects in GCP. Create an "OAuth client ID" according to Quickstart.

  1. If not enabled, enable the Drive API from the GCP console --Go to https://console.cloud.google.com/apis/api/drive.googleapis.com/overview --In this article, we have enabled the Drive API in the "Drive-Template-Copy" project and created an OAuth client ID.

  2. Create OAuth client ID (enter document value) --Recommended operation from API and Service Dashboard --Create from "Authentication Information" in the navigation on the left 1-create_oauth_client_id.png → Enter the setting value in Quickstart 2-fill_out_creation_form.png → Created (this pop-up is closed by clicking "OK") 3-complete_creation.png

  3. After creating, download the authentication information to the development terminal 4-download_client_id.png --Move your credentials to your working directory and rename it to client_secrets.json

2. Operation check

Refer to Quickstart and run the following code.

quickstart.py


from pydrive2.auth import GoogleAuth  #Read pydrive as pydrive2 from Quickstart

gauth = GoogleAuth()
gauth.LocalWebserverAuth()

File placement


.
├── client_secrets.json
└── quickstart.py

Running quickstart.py will launch your browser.

$ python quickstart.py
Your browser has been opened to visit:

    https://accounts.google.com/o/oauth2/auth?client_id=...
5-login_google.png

When you select a Google account and log in, 6-authentication_completed.png

The command line also shows that the authentication was successful!

$ python quickstart.py
Your browser has been opened to visit:

  :

Authentication successful.

I want to prevent the browser from starting every time

Go to the PyDrive documentation OAuth made easy.

With just two lines of code, I've been authenticated to use the Drive API. It's pretty easy, but you have to log in from your browser every time you run this script. This is not suitable for scripted automation. Therefore, we will set PyDrive2 to save the information used for authentication and update it automatically after that. Once you log in, the saved credentials will be updated and used, eliminating the need to log in from your browser.

To achieve the above, write settings.yaml. The settings for saving the authentication information to a file are as follows.

settings.yaml


# OAuth 2.0 Specify (rename) client authentication information
client_config_file: my_client_secrets.json

#Settings to save credentials to a file
save_credentials: True
save_credentials_backend: file
save_credentials_file: saved_credentials.json

#Authentication information(credentials)Setting to update automatically (browser does not start)
get_refresh_token: True

File placement


.
├── my_client_secrets.json
├── quickstart.py
└── settings.yaml

Running python quickstart.py on the command line requires you to log in from your browser the first time. 7-login_google-again.png

A warning page will be displayed depending on the scope of operation using the Drive API (scope * described later). "Show details" to move. 8-unverified_page.png

9-allow_access_private_data.png

If you allow it, your browser will display "The authentication flow has completed".

Authentication using a browser is only the first time. Since get_refresh_token is enabled [^ 1], the browser will not start because the authentication information is automatically updated and authenticated from the second time onward [^ 2].

File placement


.
├── my_client_secrets.json
├── quickstart.py
├── saved_credentials.json  #Created. After that, it will be updated automatically
└── settings.yaml

[^ 1]: Every time I change the value of get_refresh_token, it seems that I need to log in with a browser for the first time. It is recommended to delete the saved credentials and re-execute (I enabled get_refresh_token with saved_credentials.json in the past, but it was not reflected and I was addicted to it. I wonder if the items of the returned data are different. "

[^ 2]: It seems that the authentication information may not be updated automatically after a period of time. When I touched it for the first time in a while, an error occurred. I deleted the saved credentials (saved_credentials.json) and re-executed to resolve it.

Supplementary information

Drive API scope

There is an item called ʻoauth_scope in settings.yaml[^ 3]. Since it is not specified this time, the default value is[‘https://www.googleapis.com/auth/drive’]. According to the Drive API Scope List (https://developers.google.com/drive/api/v2/about-auth#OAuth2Authorizing), this is a Restricted` scope. Apps that require a restricted scope and have not passed Google's verification process will be labeled as "Unverified app" and the previous "This app has not been verified" page will be displayed. [^ 4].

According to https://support.google.com/cloud/answer/7454865, you need to add https://www.googleapis.com/auth/drive to the" OAuth consent screen ". There is. However, simply adding it wasn't enough, and I had to apply for Google's verification.

What you want to achieve by working with Google Drive in Python is, at this stage, personal automation. Since we are not developing an app for use by a third party, we will not proceed to the approval process and will continue to develop it as it is [^ 5].

[^ 4]: From https://support.google.com/cloud/answer/7454865. "An unverified app is an app or Apps Script that requests a sensitive or restricted OAuth scope, but hasn't gone through the Google verification process"

[^ 5]: "Apps in development: if your app is experimental or a test build, you don't need to go through verification unless you decide to launch it to the public." Https://support.google.com/ From cloud / answer / 7454865

LocalWebserverAuth and CommandLineAuth

I changed LocalWebserverAuth to CommandLineAuth to prevent the browser from launching the first time I logged in, but it didn't work.

From the "authorization error" displayed on the browser, the OAuth client ID is * created as a web application *, so it seems that it does not support CommandLineAuth.

could_not_use_commandlineauth.png

Therefore, I think it is essential to log in with the browser for the first time [^ 6].

[^ 6]: In the execution environment where the browser cannot be started, the saved authentication information is duplicated and placed (the browser does not start, so it can be executed without problems).

settings.yaml and client_secrets.json

If settings.yaml and client_secrets.json are in the same directory as quickstart.py, it seems that settings.yaml will be loaded. I was curious, so I took a look at the [Implementation] of GoogleAuth in ʻauth.py` (https://github.com/iterative/PyDrive2/blob/d2065b42a4c6cc39fb6666a278b361d2c59ab8c2/pydrive2/auth.py#L142). ..

--The call GoogleAuth () means that " settings.yaml " (default value) was specified. --If you rename settings.yaml, you should pass it to the argument of GoogleAuth. --Settings.yaml is loaded while executing GoogleAuth () --The client_config_file specified in settings.yaml is used --If not specified in settings.yaml, " client_secrets.json " is used as the default value.

In this article

--client_secrets.json is used before creating settings.yaml --After creating settings.yaml, the client_config_file specified there will be used.

There are.

Recommended Posts

Around the authentication of PyDrive2, a package that operates Google Drive with Python
A story that struggled to handle the Python package of PocketSphinx
The story of making a module that skips mail with python
[Python] A program that counts the number of valleys
Make a copy of a Google Drive file from Python
A memo that I touched the Datastore with python
[Python] A program that compares the positions of kangaroos.
Access Google Drive with Python
Duplicate the document template prepared in Google Drive with PyDrive2
A Python script that compares the contents of two directories
A record of patching a python package
A memorandum of understanding for the Python package management tool ez_setup
[Python] Make a graph that can be moved around with Plotly
I made a package that can compare morphological analyzers with Python
Save the result of the life game as a gif with python
[python, ruby] fetch the contents of a web page with selenium-webdriver
The story of making a standard driver for db with python.
A function that measures the processing time of a method in python
The idea of feeding the config file with a python file instead of yaml
[python] A note that started to understand the behavior of matplotlib.pyplot
[Python] A program that rotates the contents of the list to the left
Create a compatibility judgment program with the random module of python.
[Python] A program that finds the maximum number of toys that can be purchased with your money
The story of creating a bot that displays active members in a specific channel of slack with python
Notes around secrets authentication when implementing a simple application that performs slack notification with github webhook in google cloud function (python)
[Python] A program that creates stairs with #
A story that visualizes the present of Qiita with Qiita API + Elasticsearch + Kibana
[Python] A program that calculates the number of chocolate segments that meet the conditions
The story of making a university 100 yen breakfast LINE bot with Python
[AtCoder explanation] Control the A, B, C problems of ABC182 with Python!
Calculate the shortest route of a graph with Dijkstra's algorithm and Python
How to run the practice code of the book "Creating a profitable AI with Python" on Google Colaboratory
Get the number of searches with a regular expression. SeleniumBasic VBA Python
[Python] A program that calculates the number of socks to be paired
Check the existence of the file with python
[AtCoder explanation] Control the A, B, C problems of ABC186 with Python!
Extract lines that match the conditions from a text file with python
Search the maze with the python A * algorithm
[Introduction to Python] How to sort the contents of a list efficiently with list sort
I tried to get the authentication code of Qiita API with Python.
[AtCoder explanation] Control the A, B, C problems of ABC185 with Python!
Calculate the probability of being a squid coin with Bayes' theorem [python]
Hit a method of a class instance with the Python Bottle Web API
[python] [meta] Is the type of python a type?
Receive a list of the results of parallel processing in Python with starmap
A typed world that begins with Python
The result of making the first thing that works with Python (image recognition)
[AtCoder explanation] Control the A, B, C problems of ABC187 with Python!
The story of making a package that speeds up the operation of Juman (Juman ++) & KNP
The story of blackjack A processing (python)
From a book that makes the programmer's way of thinking interesting (Python)
[Python] A program that rounds the score
Upload images to Google Drive with Python
[AtCoder explanation] Control the A, B, C problems of ABC184 with Python!
[Python] Note: A self-made function that finds the area of the normal distribution
Article that can be a human resource who understands and masters the mechanism of API (with Python code)
I took a quick look at the fractions package that handles Python built-in fractions.
About the problem that the python version of Google App Engine does not mesh
[AtCoder explanation] Control the A, B, C, D problems of ABC183 with Python!
The story of making a web application that records extensive reading with Django
Periodically notify the processing status of Raspberry Pi with python → Google Spreadsheet → LINE