OAuth2 and Google

Tony Pitale edited this page Nov 3, 2016 · 21 revisions

Getting an OAuth2 Token

Assuming your application will simply use Google Analytics, the following are instructions on how to generate a read-only OAuth token for access to Google for use in your testing. Any code you build will have to handle generating and storing this access token. Note: I would advise reading up on how OAuth2 works before starting work. This is only a brief introduction.

There are two main types of access--one prompts the user for authorization in-browser, and expires after an hour (but can be renewed). The other only uses your account, but it does not require in-browser authorization and expires after an hour. This is called a service account, and is discussed at the bottom of this page.

Registering for API Access with Google OAuth

  • Go to the Google API Console
  • Create a new Project and name it accordingly
  • Turn on the Google Analytics access
  • Click API Access in the left column
  • Click Create an OAuth
    • Enter a product name, and add an optional logo
    • Click next
    • Select Installed Application (for testing) or Web Application (for deployed web apps)
    • Click create client id
  • Make sure your Redirect URIs include http://localhost, exactly that way.
  • On the API Access page, find Client ID and Client secret.

Generate token

The following are instructions about how to generate the auth code you will need in your final application. First install oauth2.

$ gem install oauth2

We will store the secure keys in environment variables as this is a good practice for your application, but it would be trivial to use a configuration file if that is your preference.

$ export LEGATO_OAUTH_CLIENT_ID='your_client_id_from above'
$ export LEGATO_OAUTH_SECRET_KEY='your_secret_key_from above'

Start up the Ruby console

 $ irb
 > require 'oauth2'

Create an OAuth client object

client = OAuth2::Client.new(ENV['LEGATO_OAUTH_CLIENT_ID'], ENV['LEGATO_OAUTH_SECRET_KEY'], {
  :authorize_url => 'https://accounts.google.com/o/oauth2/auth',
  :token_url => 'https://accounts.google.com/o/oauth2/token'
})

Create the authorize URL.

client.auth_code.authorize_url({
  :scope => 'https://www.googleapis.com/auth/analytics.readonly',
  :redirect_uri => 'http://localhost',
  :access_type => 'offline'
})

The above will output a URL string. Copy this and go to it in your browser. Google will ask you to authorize this new token. Then it will take you to a URL like the following, and you should copy the your_new_auth_code part.

http://localhost/?code=your_new_auth_code

Get out of the Ruby console, and set the new auth code in an environment variable. This is only good for a single use.

$ export LEGATO_OAUTH_AUTH_CODE='your_new_auth_code_from above'

Generate the Access Token (good for 30 minutes)

Now we have all the parts we need for the application, so you can include this code in your application.

client = OAuth2::Client.new(ENV['LEGATO_OAUTH_CLIENT_ID'], ENV['LEGATO_OAUTH_SECRET_KEY'], {
  :authorize_url => 'https://accounts.google.com/o/oauth2/auth',
  :token_url => 'https://accounts.google.com/o/oauth2/token'
})
client.auth_code.authorize_url({
  :scope => 'https://www.googleapis.com/auth/analytics.readonly',
  :redirect_uri => 'http://localhost',
  :access_type => 'offline'
})
access_token = client.auth_code.get_token(ENV['LEGATO_OAUTH_AUTH_CODE'], :redirect_uri => 'http://localhost')

response_json = access_token.get('https://www.googleapis.com/analytics/v3/management/accounts').body

JSON.parse(response_json)

## Or if you have already gathered and saved the access token earlier
token = 'A_TOKEN_I_ALREADY_HAVE'
client = OAuth2::Client.new(ENV['LEGATO_OAUTH_CLIENT_ID'], ENV['LEGATO_OAUTH_SECRET_KEY'], {
  :authorize_url => 'https://accounts.google.com/o/oauth2/auth',
  :token_url => 'https://accounts.google.com/o/oauth2/token'
})
client.auth_code.authorize_url({
  :scope => 'https://www.googleapis.com/auth/analytics.readonly',
  :redirect_uri => 'http://localhost',
  :access_type => 'offline'
})
access_token = OAuth2::AccessToken.from_hash client, {:access_token => token}

Service Accounts

Note: Service accounts only work for Google Apps accounts. With a regular @gmail.com google account, you'll need an "Installed Application". To make this easier, some folks have created google-oauth2-installed.

Registering for API Access

  • Go to the Google API Console
  • Create a new Project and name it accordingly
  • Turn on the Google Analytics access
  • Click API Access in the left column
  • Click Create an OAuth
    • Enter a product name, and add an optional logo
    • Click next
    • Select Service Account
    • Click create client id
  • Download the P12 private key, and keep it somewhere safe
  • Note the @developer.gserviceaccount.com email address that is displayed under the Service account section of the page.
  • Go to Google Analytics
  • Click Admin
  • Click the Users tab
  • Add a new user with that email address.

More info on service accounts.

Application Code

The OAuth2 gem does not easily support using private keys, so we will use the Google API Client gem to help. In your Gemfile:

gem 'signet'

Then use the following code to create a Legato user, replacing the capitalized strings as appropriate:

require 'signet/oauth_2/client'

def service_account_user(scope = 'https://www.googleapis.com/auth/analytics.readonly')
  key         = OpenSSL::PKCS12.new(File.read('YOUR_PRIVATE_KEY_FILENAME'), 'notasecret').key
  auth_client = Signet::OAuth2::Client.new(
                  token_credential_uri: 'https://accounts.google.com/o/oauth2/token',
                  audience: 'https://accounts.google.com/o/oauth2/token',
                  scope: scope,
                  issuer: 'YOUR_API_EMAIL_ADDRESS@developer.gserviceaccount.com',
                  signing_key: key,
                  sub: 'YOUR_API_EMAIL_ADDRESS@developer.gserviceaccount.com')

  access_token = auth_client.fetch_access_token!

  oauth_client = OAuth2::Client.new('', '', {
    authorize_url: 'https://accounts.google.com/o/oauth2/auth',
    token_url: 'https://accounts.google.com/o/oauth2/token'
  })

  token = OAuth2::AccessToken.new(oauth_client, access_token['access_token'], expires_in: access_token['expires_in'])

  user  = Legato::User.new(token)

  # after an hour or so
  user.access_token.expired?
end

If you download the JSON file instead of the P12 file, you can replace the key line OpenSSL::PKCS12 … with key = OpenSSL::PKey::RSA.new(private_key) where private_key comes from the JSON private key value.

For more details refer to Issue 32. And more recently: Issue 90.