Google Account Authorization: ClientLogin vs. OAuth 2.0
Update May 13, 2011: Since I posted this, the session talk has been posted to YouTube. Dirk Balfanz, the gentleman that gave the talk, has contacted me via email with some helpful thoughts. I appreciate the response and knowing that Google is listening.
I was unable to attend the Google I/O conference this year, but I have been monitoring the news coming out of the conference with great interest.
One of the sessions was named ClientLogin #FAIL. The summary of the session discusses reasons that apps using ClientLogin for Google account authorization should migrate towards OAuth 2.0. My app, CloudPull, uses ClientLogin. Google has made it clear that ClientLogin is deprecated. I am typically eager to avoid using deprecated API's, but I am very hesitant to migrate the CloudPull authorization mechanism from ClientLogin to OAuth 2.0.
ClientLogin allows the client app to build its own user interface around entering credentials. In the CloudPull first time user setup, the window looks like this:
This approach is not perfect. The protocol does not handle two-factor authentication in a particularly smooth manner. In order to do so, the ClientLogin protocol would need to be updated and every app using that protocol would need to be updated to allow two-factor authentication. The more generalized problem is that client apps need to be aware of any piece of information Google may ask for during the authentication process.
It is understandable, therefore, that Google wants to migrate towards OAuth. In general, OAuth tells the app to bring up a Google web page. The web page asks the user to identify himself or herself in any way that page chooses. The mechanism would typically be a username and password, but additional items such as captcha's, two-factor authentication codes, and secret question/answer combinations could also be included.
My biggest concern with OAuth 2.0, and specifically the Google implementation of OAuth 2.0, is that a Mac-native app bringing up a web page for asking for credentials is very awkward. I see no way to do that without compromising the user experience. In addition, CloudPull still needs the username and password to access calendars via CalDAV. A future version of CloudPull is very likely to need the username and password to access email via IMAP. My impression is that Google will eventually provide OAuth 2.0 access to IMAP, but is in no hurry to provide OAuth 2.0 access to calendars via CalDAV.
Finally, there are other weaknesses in the OAuth 2.0 implementation:
- There is no read-only scope for Google Docs, Google Calendar, or Google Contacts. When an app requests OAuth 2.0 access to Google Docs, the authorization page tells customers that they are providing access to "manage" and "upload" data. Since CloudPull only ever reads Google data, this is likely to alarm customers.
- The implementation does not provide a good way for the app to force the user to log in to a specific account (Ticket 2488).
- There is no programmatic method of getting an OAuth 2.0 token based on a username and password (Ticket 2487). This makes it challenging to migrate existing customers from ClientLogin to OAuth 2.0 without manual effort on their part.
Google could provide a programmatic method of getting an OAuth 2.0 token based on a username, password, and list of API scopes. The OAuth specification specifically allows this. For specific accounts or circumstances that may require a captcha, two-factor authentication code, or something else relatively non-standard, falling back to displaying a web page would still be an option.
As an app developer, I am left with three choices:
- Continue writing to a deprecated API.
- Migrate towards OAuth 2.0, sacrificing the user experience of my customers.
- Write code to simulate navigating the login process in the background, screen scraping the resulting pages.
Sadly, continuing to use the deprecated API is the most appealing of these options.
If anyone at Google reads this and wants to contact me directly, I am at email@example.com.
Thank you for reading.