Suyeon Son and David Eads re-worked the authentication mechanism for accessing Google Spreadsheets with the NPR Visuals App Template. This is a significant change for App Template users. Here’s why we did it and how it works.
Most App Template developers only need to consult the Configuring your system and Authenticating sections of this post, provided someone on your team has gone through the process of creating a Google API application and given you credentials.
Prior to this change, the App Template accessed Google spreadsheets with a user account and password. These account details were accessed from environment variables stored in cleartext. Storing a password in cleartext is a bad security practice, and the method led to other dubious practices like sharing credentials for a common Google account.
OAuth is a protocol for accessing online resources on behalf of a user without a password. The user must authenticate with the service using her password to allow the app to act on her behalf. In turn the app receives a magic access token. Instead of directly authenticating the user with the service, the application uses the token to access resources.
There are many advantages to this approach. These access tokens can be revoked or invalidated. If used properly, OAuth credentials are always tied to an individual user account. An application can force all users to re-authenticate by resetting the application credentials. Accessing Google Drive resources with this method is also quite a bit faster than our previous technique.
Setting up the Google API application
To use the new OAuth feature of the App Template, you will need to create a Google API project and generate credentials. Typically, you’ll only need to do this once for your entire organization.
Visit the Google Developer’s Console and click “Create Project”.
Give the project a name for the API dashboard and wait for the project to be created:
Give the project a name again (oh, technology!) by clicking “Consent screen” in the left hand toolbar:
Enable the Drive API by clicking “APIs” in the left hand toolbar, searching for “Drive” and enabling the Drive API:
You can optionally disable the default APIs if you’d like.
Finally, create client credentials by clicking “Credentials” in the left hand toolbar and then clicking “Create New Client ID”:
Now you have some credentials:
Configuring your system
Whew! Happily, that’s the worst part. Typically, you should only do this once for your whole organization.
Add some environment variables to your
.bash_profile or current shell session based on the client ID credentials you created above:
As you can see above, you also need to set a random string to act as cryptographic salt for the OAuth library the App Template uses.
fab app in your App Template project and go to localhost:8000 in your web browser. You’ll be asked to allow the application to access Google Drive on behalf of your account:
If you use multiple Google accounts, you might need to pick one:
Google would like you to know what you’re getting into:
That’s it. You’re good to go!
Bonus: Automatically reloading the spreadsheet
Any route decorated with the
@oauth_required decorator can be passed a
refresh=1 querystring parameter which will force the latest version of the spreadsheet to be downloaded (e.g. localhost:8000/?refresh=1).
This is intended to improve the local development experience when the spreadsheet is in flux.
Behind the scenes
The new system relies on the awesome Authomatic library (developed by a photojournalist!).
We provide a decorator in
oauth.py that wraps a route with a check for valid credentials, and re-routes the user through the authentication workflow if the credentials don’t exist.
Here’s an example snippet to show how it works:
Authomatic provides an interface for serializing OAuth credentials. After successfully authenticating, the App Template writes serialized credentials to a file called
~/.google_oauth_credentials and reads them when needed.
By using the so-called “offline access” option, the credentials can live in perpetuity, though the access token will change from time-to-time. Our implementation hides this step in a function called
get_credentials which automatically refreshes the credentials if necessary.
By default, credentials are global – once you’re authenticated for one app template project, you’re authenticated for them all. But some projects may require different credentials – perhaps you normally access the project spreadsheet using your
USERNAME@YOURORG.ORG account, but for some reason need to access it using your
OTHERUSERNAME@GMAIL.COM account. In this case you can specify a different credentials file in
app_config.py by changing
Finally, the Google Doc access mechanism has changed. If you need to access a Google spreadsheet that’s not involved with the default COPY rig, use the new
get_document(key, file_path) helper function. The function takes two parameters: a spreadsheet key and path to write the exported Excel file. Here’s an example of what you might do: