Once you get beyond the basics of adding Google+ Sign-In, and start looking at what is available across the Google platform there are some real gems to be found. One of these is a fantastic feature of Google Drive called appdata, which allows an application to store data in a user’s Drive account without worrying about the user fiddling with it. These is handy if you’re building something like a Javascript web app and need some storage, but don’t want to setup a server. Unlike localStorage or other browser based options it doesn’t rely on the user being on the same device, so it’s easy to allow users to access their data from wherever they are.
Most of the time this sort of feature seems a natural fit for mobile applications - as Drive is about manipulating files - but it’s just a straightforward to build it in to a web application. There’s a little form in the iframe below - you can sign in and save your data, and then if you sign in to another device you should have the same data available.
All this is doing is syncing the contents of the form to a state variable, and then reading and writing that state value to a file in the Drive appdata storage.
Setup
In order to gain access to the Drive app data folder, we need to request the appropriate scope, https://www.googleapis.com/auth/drive.appdata. We do this in addition to the regular plus.login scope for Google+ Sign-In in the scope parameter of the sign-in button.
This causes an extra consent line to appear. “View and manage its own configuration data in your Google Drive”. Once the user accepts, in the onSignin callback we load the Google Drive Javascript API client and see if we have any existing state to retrieve.
Checking for the file
The app data is implemented in Drive as a special folder which only our app can write to. Because of that, we need to check whether our config file is available. The first step is to get a list of files in the folder, and look for one with the name of our config file.
Where we use the file.list method with a search query: ‘appdata’ in parents. This requests all files that are in the app data folder. appdata is a special string, much like “me” in Google+ sign-in, that refers to the folder of the currently connected application. We loop over the files and store the ID of the first file that matches our config filename. FILENAME in this case is just the constant we’re using for the filename. In the sample it is ‘appsettings.json’. The first time we connect there won’t be a stored file. This will leave the file ID as null and use the local defaults in the state variable.
Saving the file
When the user hits submit for the first time, we need to actually create the file. This is done via a form post to a specific upload URL. We’ll use the FormData object to actually create our multipart form post, consisting of a blob of JSON for the metadata, and the file data itself. The metadata defines our file name, the content type, and importantly that the file is in the appdata folder. The main file body in this case is also a JSON blob, so we just stringify both and add them to our form object.
There is a standard URL for these type of file uploads which we can POST our multipart form to. In future, once we have a file ID for our config file we can PUT to an address which includes the ID in order to update it.
Note that we include the OAuth 2.0 access token as a header on the post via the JQuery ajax call. We also disable local processing by JQuery so it passes through the form data properly.
Reading the file
Finally, we need to read the config file back when the user returns. To do this we make an API call with the file ID we saved from the list operation. This gives us to get a download URL that we can then fetch with an XHR. Because the file type is application/json, we can immediately treat that like an object and fill the form. One optimisation for a real system would be to store this file ID in local storage to save a network roundtrip for returning users on the same browser.
Again, we put the access token in the header while downloading. Once we have the file, we can just set our local state variable to the contents and again sync the form.
These same approaches can work from any client that can talk to the Drive APIs, which is almost anything. This means you could have the same config for native Android, iOS, and desktop apps as well as your web sign-in.