If you uninstall our Chrome extension, a form pops up asking you for a reason, and one of the most common reasons given is that the permissions GMass requires of your Google account are too invasive. We ask for access to your Gmail account, your Google Sheets, and partial access to your Google Drive via Google’s OAuth 2 scheme. This is all so that various email campaign functionality works.
We are verified and approved by Google, which requires going through a lengthy process and security audit. Still, the average user doesn’t know that and fears their data is at risk if they connect GMass to their Google account. One of the best practices for implementing Google’s OAuth is to use incremental authorization, which means requesting a scope only as it’s needed. For example, GMass is heavily integrated with Google Sheets, but you don’t actually need to use Google Sheets to send an email campaign since you can also just paste a bunch of addresses into the Gmail Compose window and send that way rather than connecting to a Sheet. Therefore, I recently explored the idea of not requesting Sheets permissions upon sign-up, and instead, requesting Sheets permissions only if the user clicks the Sheets connector button. This, I was hoping, would make signing up more palatable for privacy-conscious users. Further, I was hoping Google’s incremental authorization program would make this easy, but after delving into what the program offers, I was sorely disappointed.
Here’s what I thought incremental authorization would do. I thought it would allow me to request access to scope X, and assuming the scope was granted, then if I later requested access to a different scope Y, and the user consented to that additional scope, the new token provided would give me access to both scopes.
What actually happens is that when you request access to scope Y, the user is told the app is asking for permissions for scope X and scope Y. This presents an issue because it can make me, the software developer, look sloppy. If upon sign-up, we ask for the Gmail scope, and then when you click the Sheets connector button, we request the Sheets scope, the consent screen says we’re requesting permissions for Gmail and Sheets. So, we look dumb because the user knows he already granted us permission for Gmail a couple of minutes ago. The fact that Google again requests from the user all previously granted scopes makes for an awkward experience for both the user and the developer. Google’s intent is likely to remind the user just how much permission the app has, but in doing so, they risk scaring the user out of consenting, which is the problem that incremental authorization is meant to solve in the first place.
In fact, the documentation even states:
“To implement incremental authorization, you complete the normal flow for requesting an access token but make sure that the authorization request includes previously granted scopes.”
I’m supposed to include “previously granted scopes” in my new request? Hmm, that sounds like the work of implementing incremental authorization falls on me, not Google. How is Google helping? By the way, you can also accomplish this by setting include_granted_scopes=true in your initial OAuth request, in which case Google does dig deep into its database to determine what scopes have already been granted and re-presents those to the user so that you don’t have to include previously granted scopes in your request. I don’t know why this paragraph doesn’t mention that, but the problem is still the same. If you don’t include previously granted scopes yourself or set the include_granted_scopes flag to true, then you would get a new token with access only to that scope, and now your application has to keep track of multiple tokens. Boo. It turns out, that is the only way to accomplish what I want, which is to show the user only the additional scope that I’m requesting.
In case this isn’t clear, let’s say I’m having dinner at a restaurant. I’m finished with my appetizer and entree, and now the server is taking my dessert order. The conversation goes like this.
Me: I’m considering the chocolate cake; what do you think of the chocolate cake?
Server: The chocolate cake is a good choice, but just to remind you, you had the jalapeño poppers and nachos for your appetizer, and you had a double cheeseburger with fries and extra mayo for your entree. You sure about that chocolate cake?
If you’re a SQL Server DBA, you’ve heard of full backups and differential backups. A differential backup is a backup of everything in the database since the last full backup. An incremental backup is a backup of everything since the last incremental backup. Using this model as a framework, we can conclude that Google’s OAuth 2 implementation actually features differential authorization and not incremental authorization.
The “incremental authorization” program should take a page out of the Chrome extension developer guide, which also features an incremental authorization for extension scopes. Here, however, when you request one scope and then later request another, the user is only asked to grant that other individual scope, but behind the scenes, Google grants the extension the combined set of scopes. That’s true incremental authorization.
A better approach would be for Google to:
a. Look at the scopes that the application is requesting, and any scopes that have already been granted need not show up on the consent screen. So, if the app has already been granted access to Gmail, and now the app requests access to Gmail and Sheets, the user would be shown a consent screen asking to authorize access just to Sheets. Or,
b. If solution “a” isn’t satisfactory, then Google could present a screen that shows which scopes have already been granted and which new scopes are currently being requested. In the above example, the consent screen could say, “This app is requesting access to your Sheets,” with a section underneath that says, “This app ALREADY has access to your Gmail account.”
Will Google make this change? Perhaps incrementally.