0

I use Garb(0.9.8) to fetch data from Google Analytics from our server directly using OAuth1. As Google only supports OAuth2 now so I switched to Signet gem and used a service account to get a access_token from the server directly as we need only server to server interaction.

key = Google::APIClient::KeyUtils.load_from_pkcs12(p12_key_path, 'notasecret')
client = Google::APIClient.new(application_name: 'Service account demo', application_version: '0.0.1')
client.authorization = Signet::OAuth2::Client.new(
  :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
  :audience => 'https://accounts.google.com/o/oauth2/token',
  :scope => ['https://www.googleapis.com/auth/analytics', 'https://www.googleapis.com/auth/analytics.readonly'],
  :issuer => <service account email>,
  :signing_key => key
)

access_token = client.authorization.fetch_access_token!["access_token"]

The token is valid and i double checked it from the Google API playground. The service account has been added as a user with all permissions to my Google Analytics account. If feasible I wanted to use Garb instead of completely switching to google-api-client gem so as to avoid re-writing a lot of exisiting code. Then to make Garb use the access_token obtained and fetch all profiles I did the following

garbsession = Garb::Session.new
garbsession.access_token = access_token
Garb::Management::Profile.all(garbsession)

But I am getting an error:

NoMethodError: undefined method `get' for #<String:0xd877aa0>
    from /home/alok/.rvm/gems/ruby-1.9.3-p385/gems/garb-0.9.8/lib/garb/request/data.rb:94:in `oauth_user_request'
    from /home/alok/.rvm/gems/ruby-1.9.3-p385/gems/garb-0.9.8/lib/garb/request/data.rb:41:in `send_request'
    from /home/alok/.rvm/gems/ruby-1.9.3-p385/gems/garb-0.9.8/lib/garb/management/feed.rb:21:in `response'
    from /home/alok/.rvm/gems/ruby-1.9.3-p385/gems/garb-0.9.8/lib/garb/management/feed.rb:13:in `parsed_response'
    from /home/alok/.rvm/gems/ruby-1.9.3-p385/gems/garb-0.9.8/lib/garb/management/feed.rb:17:in `entries'
    from /home/alok/.rvm/gems/ruby-1.9.3-p385/gems/garb-0.9.8/lib/garb/management/profile.rb:14:in `all'
    from (irb):47
    from /home/alok/.rvm/gems/ruby-1.9.3-p385/gems/railties-3.2.19/lib/rails/commands/console.rb:47:in `start'
    from /home/alok/.rvm/gems/ruby-1.9.3-p385/gems/railties-3.2.19/lib/rails/commands/console.rb:8:in `start'
    from /home/alok/.rvm/gems/ruby-1.9.3-p385/gems/railties-3.2.19/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

Am I doing something wrong? Can I use an Access token obtained by some other method in Garb and then access the Google Analytics API ?

Alok Swain
  • 6,409
  • 5
  • 36
  • 57
  • can you change your code for finding profiles as: Garb::Management::Profile.all, removing garb session – Adnan Devops Jun 05 '15 at 13:14
  • I will guide you to use https://github.com/tpitale/legato gem for analytics stuffs...its an awesome gem. – Adnan Devops Jun 05 '15 at 13:18
  • @AdnanDevops - Garb::Management::Profile.all doesnt work too. I will try Legato, but from what I see it offers some more features which we dont require yet. – Alok Swain Jun 05 '15 at 13:28
  • Yes legato provides a lot of nice features but it's worth giving a try. – Adnan Devops Jun 05 '15 at 14:40
  • @AdnanDevops - I obtained a OAuth2 access token using omniauth-google-oauth2 gem. Used Legato `user = Legato::User.new(access_token)`. Executing `user.profiles` gives error `NoMethodError: undefined method `get' for # from /home/alok/.rvm/gems/ruby-1.9.3-p385/gems/legato-0.4.0/lib/legato/management/finder.rb:11:in `all' from /home/alok/.rvm/gems/ruby-1.9.3-p385/gems/legato-0.4.0/lib/legato/user.rb:47:in `profiles' from (irb):7` - Am I doing something wrong ? – Alok Swain Jun 06 '15 at 09:42
  • Give me some time I wil help you with the solution... – Adnan Devops Jun 06 '15 at 13:54
  • Could you paste your user object here? – Adnan Devops Jun 06 '15 at 13:57

1 Answers1

2

The mistake I made is Garb::Session.access_token should be an instance of OAuth2 client and not the access token itself. I am posting the working code in my answer so that it might help other later !. Came across the code when browsing the Legato gem for a solution to the problem. Github issue link from where I found the solution- https://github.com/tpitale/legato/issues/90

p12_key_path = File.join(Rails.root, "config", <p12_key_path>)
key = Google::APIClient::KeyUtils.load_from_pkcs12(p12_key_path, 'notasecret')
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: 'https://www.googleapis.com/auth/analytics.readonly',
  issuer: <ga_service_account email>,
  signing_key: key
)
access_token = auth_client.fetch_access_token!
raise "Google OAuth Access Token is blank" if access_token["access_token"].blank?
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: 1.hour)
Garb::Session.access_token = token

profile = Garb::Management::Profile.all
Alok Swain
  • 6,409
  • 5
  • 36
  • 57