4

I need to connect to Google Analytics. I'm using omniauth_google_oauth2 for authenticating the user with the app, and this gives me a token. The problem is that I need to connect to this user's Google Analytics account. To connect GA to my app I'm using the garb gem which has only two methods for authentication; username/password, and OAuth token. When I use the token provided by omniauth_google_oauth2, it doesn't work.

How do I create this new token using only the oauth_token that I get from the authentication with omniauth_google_oauth2?

alexmuller
  • 2,207
  • 3
  • 23
  • 36

2 Answers2

2

I know I'm late to the party on this one but I solved a similar issue. You can't use omniauth_google_oauth2 with garb unless you use a fork of garb that supports oauth2. There is one here that is well maintained by Sija. However, you will need to use an oauth2 client object in order to create a session with this fork. You can get your user's profile set up using omniauth_google_oauth2 and make sure you save the refresh token for the user, then when you want to grab analytics data with garb, refresh the token with oauth2 and then pass that object into your garb session to pull the user's data. Here's an example after you have the refresh_token from omniauth stored somewhere:

client = OAuth2::Client.new YOURGOOGLEAPIKEY, YOURGOOGLEAPISECRET,
                                {
                                  :site => 'https://accounts.google.com',
                                  :authorize_url => "/o/oauth2/auth",
                                  :token_url => "/o/oauth2/token",
                                }
response = OAuth2::AccessToken.from_hash(client, :refresh_token => omniauth_refresh_token).refresh!
Garb::Session.access_token = response
topher
  • 301
  • 1
  • 5
  • 14
  • 1
    I'd love for you to expand on this a little bit. I think the OAuth2 with Sija's Garb fork is right way to solve this. I can't seem to pull this off. – adamb0mb Mar 20 '13 at 04:02
  • What part specifically are you having trouble with? Is it getting a refresh_token from omniauth_google_oauth2, refreshing it, setting up sija's fork, or using the refresh response to start a garb session? – topher Mar 21 '13 at 22:33
  • I figured it out... I think I was just having issue making it work with `irb`. Your snippet is spot on. – adamb0mb Mar 22 '13 at 05:58
  • Sija's fork now seems to be preferred version. I can confirm it's working great with omniauth_google_oauth2 and garb. – Andy Triggs Apr 23 '13 at 20:22
  • Topher - thanks for your write up... this helped me months ago when I got it to work. Recently though my app stopped working, giving an error code: invalid_grant: { "error" : "invalid_grant" } Have you experienced this? Any insight into what might be going on? – Cam Norgate Jul 26 '13 at 11:26
1

I think the problem you're encountering is that garb will only authenticate a user using OAuth 1 (or a username/password combo), while omniauth_google_oauth2 is (obviously) OAuth 2.

The only solution I've found is to use Google's deprecated OAuth 1 implementation as follows...

Gemfile:

gem 'omniauth-google', :git => 'git://github.com/davidkpham/omniauth-google.git'
# This fork relaxes dependencies on omniauth itself

Initializer (for Google Analytics access):

provider :google, 'XXXXXXXXXXXX.apps.googleusercontent.com', 'YOUR_SECRET', scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.google.com/analytics/feeds/'

On the callback, store some of the stuff passed back:

auth = request.env["omniauth.auth"]
session[:google_token] = auth.credentials.token
session[:google_secret] = auth.credentials.secret

Then construct an AccessToken for garb:

if session[:google_token] and session[:google_secret]
  consumer = OAuth::Consumer.new('XXXXXXXXXXXX.apps.googleusercontent.com', 'YOUR_SECRET', {
    :site => 'https://www.google.com',
    :request_token_path => '/accounts/OAuthGetRequestToken',
    :access_token_path => '/accounts/OAuthGetAccessToken',
    :authorize_path => '/accounts/OAuthAuthorizeToken'
  })
  garbsession = Garb::Session.new
  garbsession.access_token = OAuth::AccessToken.new(consumer, session[:google_token], session[:google_secret])
  # Once we have an OAuth::AccessToken constructed, do fun stuff with it
  ga_id = "UA-XXXXXXX-X"
  profile = Garb::Management::Profile.all(garbsession).detect {|p| p.web_property_id == ga_id}
  ga_monthly = GoogleAnalyticsDate.results(profile, :start_date => (Date.today - 30), :end_date => Date.today, :sort => :date)
  puts ga_monthly
end
alexmuller
  • 2,207
  • 3
  • 23
  • 36
  • Thank for the great answer, it saved a ton of my time. If anyone has troubles with configuration I have a sample application which partly based on this answer: https://github.com/eicca/ga_test – Mik Aug 28 '12 at 16:28
  • Does this still work ? I am using Signet to fetch a OAuth2 access token for a service account(as i need server to server) and then created a new Garb::Session object and assigned it the access token the same way as the answer. I get an error for `Garb::Management::Profile.all(garbsession)` – Alok Swain Jun 05 '15 at 07:14