Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authorizing command line tool to consume Google APIs (through OAuth2.0 or anything else)

I think I understand how OAuth 2.0 works in the context of a mobile app or website - neither is my case.

I have a C++ command line application that I want to give access to one of the Google Services (Google Fusion Tables) but I think this question applies to any of the Google Services, or heck, perhaps also any command line app that has to deal with OAuth2.

I have the username. I have the password (the user typed it). I need to get a token so I can make the calls through Curl. What is the easiest way to accomplish this?

Update 1:

After going through the documentation, it seems that the least painful OAuth2 flow will be the "Installed Application" one.

What I am thinking is that my command line tool will make requests for public tables without needing a token (but it seems we still need to be sending an AppID from Google which I can get from the Google APIs dashboard).

Whenever my command line tool will need to use a private resource, that user would be required to supply a Google supplied authorization code (which my command line tool can then use to get a usable token). If the user has not supplied the authorization code in the command line, my tool would just print a link that the user can paste to the URL to generate the authorization code. The link would look like this:

https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/fusiontables&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&client_id=812741506391-h38jh0j4fv0ce1krdkiq0hfvt6n5amrf.apps.googleusercontent.com

Once the user accepts, she would have to paste that authorization code to the terminal so it can be used by the command line tool. The command line tool would use the authorization code to ask Google for a token and then, finally, I can then use the Google token to make the API calls.

A few things are still unclear to me. Does the authorization code change? If so, it seems I would need to save the token and refresh tokens somewhere so I can reuse the refresh token every time the token expires.

Is it just me, or does this whole thing seems like crazy talk just so that I can use a Google API from the command line?

I would normally use the ClientLogin flow, but everything seems to point out that it will be deprecated soon.

like image 503
rburhum Avatar asked Nov 10 '12 00:11

rburhum


People also ask

Is oauth2 used for authentication or authorization?

OAuth 2.0 is an authorization protocol and NOT an authentication protocol. As such, it is designed primarily as a means of granting access to a set of resources, for example, remote APIs or user's data.


1 Answers

To answer your question about the "Installed application" flow:

The authorization code is only valid once. After you have exchanged it - and got a refresh token and an access token - it won't be usable anymore. Just dump it. It's one-time use only and you don't need it anymore. What you need to do is simply keep/save/persist the refresh token in some local file for reuse.

The refresh token is the important token. It gives you access to the API for an unlimited period of time because you can use it to programmatically get new access tokens (which are valid 1h). Check the refresh token doc about that operation.

The Google APIs Client libraries usually handle refreshing the tokens automatically and transparently for you but since we don't have a C++ client lib you need to do this yourself. One technique we use is that we catch 403 errors when doing requests to the API (which indicates an invalid access token), in that case we do the refresh to get a new access token, then automatically re-try the operation that failed initially.

My advice:

The flow that will give you the best user experience is to use the server-side web application flow. It is possible to use it on installed and/or command line application, though it is more work. Here is how:

  1. Start a local web server on the user's machine listening to a free port (for instance: http://127.0.0.1:7777)
  2. Spawn a web browser window (or embed it in your app) redirecting the user to the Google OAuth 2.0 grant page and set the redirect URI to http://127.0.0.1:7777
  3. When the user grants the application access, it is redirected to your server listening at http://127.0.0.1:7777.
  4. On your local web server you get the auth code that's in a URL query parameter. You can now exchange the auth code for access and refresh tokens which you persist
  5. Kill/close the local web server you started in step 1
  6. Kill/close the browser instance you spawned in step 2

That's it, you now have the refresh and the access tokens (from step 4) and you are back in your app after killing the browser.

Why All this mess?

Client Login has been deprecated. It's going away and doesn't work with newer APIs. Google doesn't want users to give you their password, as you might be tempted to store it and you could get hacked :)) Also, it gives you access to too much information, since you could buy stuff with their Google Checkout account or change their password to steal their accounts. Currently, the only way to go on a security standpoint is to use these 3-legged auth systems like OAuth2 and discourage the use of passwords so that users get out of the habit of providing their username and password to 3rd parties. Of course, OAuth2 is a lot harder to use for desktop/command-line applications...

The OOB Alternative

If you do not want or can't start a web server to listen for the code then you can use the oob OAuth flow. It works by simply specifying oob as the redirect URI. In this case, instead of being redirected to a given URL, the user will be shown a page that says "Here is your auth code. Copy paste it into your app.". On your app you can simply have your user paste the auth code in a text field and voila. This is a worse user experience but can be more robust in some cases and work in more environment, especially low-tech environments.

Beware as not all OAuth 2 providers support that but at least Google and Facebook do.

like image 87
Nicolas Garnier Avatar answered Nov 12 '22 04:11

Nicolas Garnier