Fetching Google Analytics profiles using Garb - ruby-on-rails

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 ?

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

Related

OAuth token not retrieved with Uber API

I am unable to retrieve the token in the OAuth process using the Uber API.
Here is my code:
require 'oauth2'
<% client = OAuth2::Client.new('<client id>', '<client secret>',
:site => 'http://login.uber.com/oauth/authorize?response_type=code') %>
<% token = client.auth_code.get_token('authorization_code_value',
:redirect_uri => 'http://localhost:4567/callback',
:headers => {'Authorization' => "Token <token>"}) %>
Getting:
OAuth2::Error - invalid_client: {"error": "invalid_client"}:
/Library/Ruby/Gems/2.0.0/gems/oauth2-1.0.0/lib/oauth2/client.rb:113:in
`request'
any idea ? I tried http/https , and code/token on the response type.
thanks,
Matt
Apparently you had the wrong client id, check if it matches the one on your developer dashboard.

Rails: Export data in google spreadsheet

I am new to Rails and I want to export data to Google Spread Sheet from my web application.
I have created an app to get client id and client secret and enabled drive api for that.
I have installed google drive and google api client gem
And I used the code stated here
This code successfully runs, open a new tab for authorization, and displays a code to paste. This is the point where I am stuck. The code that google authorization demands is in my controller code so my user can paste that code in my controller. I know its quiet stupid thing to ask but I am not finding a way to automatically get the code from api to further execution as we usually do in our facebook oauth applications. So can you guide me how to do it? The code looks like
def export_spred_sheet
require 'rubygems'
require 'google/api_client'
require 'launchy'
# Get your credentials from the console
CLIENT_ID = 'YOUR_CLIENT_ID'
CLIENT_SECRET = 'YOUR_CLIENT_SECRET'
OAUTH_SCOPE = 'https://www.googleapis.com/auth/drive'
REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
# Create a new API client & load the Google Drive API
client = Google::APIClient.new
drive = client.discovered_api('drive', 'v2')
# Request authorization
client.authorization.client_id = CLIENT_ID
client.authorization.client_secret = CLIENT_SECRET
client.authorization.scope = OAUTH_SCOPE
client.authorization.redirect_uri = REDIRECT_URI
uri = client.authorization.authorization_uri
Launchy.open(uri)
# Exchange authorization code for access token
$stdout.write "Enter authorization code: "
client.authorization.code = gets.chomp
client.authorization.fetch_access_token!
# Insert a file
file = drive.files.insert.request_schema.new({
'title' => 'My document',
'description' => 'A test document',
'mimeType' => 'text/plain'
})
media = Google::APIClient::UploadIO.new('document.txt', 'text/plain')
result = client.execute(
:api_method => drive.files.insert,
:body_object => file,
:media => media,
:parameters => {
'uploadType' => 'multipart',
'alt' => 'json'})
# Pretty print the API result
jj result.data.to_hash
end
Or is there any other way to do the task If I am on wrong track?
I was also fighting against this in one of my project and finally I found soulution as follows:
Instead of using client ID and client secrete you can use P12 key generated in google developer console under service account for authentication. In this case you won't need to paste any code in controller.
To generate p12 key
go to Google developer console
then -> "APIs & Auth" -> "Credentials"
Create New Client ID of type 'Service Account'
Once new client Id generated. Under Service Account section you will find a button to 'generate new P12 key'. On click it will generate a p12 key. Download it and store it securely in your app and use it for authentication.
And use following code snippet to fetch access token.
key_file = p12_key_file_path
key = Google::APIClient::KeyUtils.load_from_pkcs12(key_file, 'notasecret')
client = Google::APIClient.new application_name: "abcd", application_version: "1.0.0"
SERVICE_ACCOUNT_ID (used in following code snippet) will be Email address generated under this "Service Account" section in google developer console.
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',
:issuer => SERVICE_ACCOUNT_ID,
:access_type => 'offline',
:signing_key => key
)
client.authorization.fetch_access_token!
client
I hope it will help you.

Ruby and Twitter: Getting Access Token from Request Token?

I am currently in Step 3 of the processing on getting an oauth token/secret from an user trying to login via Twitter. https://dev.twitter.com/docs/auth/implementing-sign-twitter
Step 3 tells me to send this request to the API, but I am stuck as to how to do so. I currently have BOTH the oauth_token and oauth_verifier, but how do I send this POST request to get the oauth_token, oauth_token_secret pair?
Is there a standard Oauth Ruby gem I can use to send this POST request? I see examples online where I pass an #accessToken object, but i do not have such an object available. I just have the oauth_token and oauth_verifier (as strings). Given these 2 things, how do I convert them to an oauth_token and oauth_token_secret?
POST /oauth/access_token HTTP/1.1
User-Agent: themattharris' HTTP Client
Host: api.twitter.com
Accept: */*
Authorization: OAuth oauth_consumer_key="cChZNFj6T5R0TigYB9yd1w",
oauth_nonce="a9900fe68e2573b27a37f10fbad6a755",
oauth_signature="39cipBtIOHEEnybAR4sATQTpl2I%3D",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1318467427",
oauth_token="NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0",
oauth_version="1.0"
Content-Length: 57
Content-Type: application/x-www-form-urlencoded
oauth_verifier=uw7NjWHT6OJ1MpJOXsHfNxoAhPKpgI8BlYDhxEjIBY
Try something like the following rails controller actions, using the twitter and oauth gems:
def redirect
consumer = OAuth::Consumer.new(CONSUMER_KEY, CONSUMER_SECRET, {
:site => "https://api.twitter.com",
:scheme => :header
})
request_token = consumer.get_request_token(:oauth_callback => CALLBACK_URL)
session[:twitter_request_token] = request_token
redirect_to request_token.authorize_url #=> "https://api.twitter.com/oauth/authorize?oauth_token=XYZ"
end
def callback
request_token = session[:twitter_request_token]
access_token = request_token.get_access_token(:oauth_verifier => params[:oauth_verifier])
client = Twitter::REST::Client.new(
:consumer_key => CONSUMER_KEY,
:consumer_secret => CONSUMER_SECRET,
:access_token => access_token.token,
:access_token_secret => access_token.secret
)
twitter_user = client.user
redirect_to root_url # or do something with the twitter_user
end
See also: http://barkingiguana.com/2009/10/13/twitter-oauth-authentication-using-ruby/
yes there is the Omniauth gem for authentication with Twitter. The documentation is straight forward.
I personally use Omniauth integrated with Devise and the Twitter gem to access Twitter - works very well.
Hope this helps,
Eugen
The common procedure is the following:
You shell to register your app on twitter development page.
Then set the proper Name, Description, and Website values up for your application.
App Name
App Description
http://your_app_domain.zone:3000/
Change Application Type is your app, by default it has read only access type.
Setup the callback URL for yuor application:
http://your_app_domain.zone:3000/auth/twitter/callback
Store the all keys, and secrets that are shewn on the OAuth tool twitter page:
Consumer key:
Consumer secret:
Access token:
Access token secret:
Setup route on your site with devise, or devise-like gem with the specified twitter keys, and secrets to enable authentication engine. The route list now shall include /auth/twitter path.
By going to http://your_app_domain.zone:3000/auth/twitter you will be redirected to twitter site, and dropped back to your site with passed oauth_token
But
You simple receive those keys, and secrets, and apply then in your app, avoiding the 6, and 7 points:
client = Twitter::REST::Client.new do |config|
config.consumer_key = "YOUR_CONSUMER_KEY"
config.consumer_secret = "YOUR_CONSUMER_SECRET"
config.access_token = "YOUR_ACCESS_TOKEN"
config.access_token_secret = "YOUR_ACCESS_SECRET"
end

how to get oauth access token for facebook using ruby

Am trying to get oauth access token for facebook programmatically in ruby.
My code is as follows:
client = OAuth2::Client.new(
APP_ID,
SECRET_ID,
:authorize_url => "/dialog/oauth",
:token_url => "/oauth/access_token",
:site => "https://www.facebook.com/"
)
code = client.auth_code.authorize_url(:redirect_uri => "http://www.facebook.com/")
token = client.auth_code.get_token(code, :redirect_uri => "https://graph.facebook.com/")
OAuth2::AccessToken.new(client, token.token, {:mode => :query, :param_name =>"oauth_token"})
When i try to run the above ruby code, i'm getting the following exception
https://www.facebook.com/dialog/oauth?response_type=code&client_id=APP_ID
51&redirect_uri=http%3A%2F%2Fwww.facebook.com%2F
/home/ec2-user/.rvm/gems/ruby-1.9.3-p0#samples/gems/oauth2-0.5.2/lib/oauth2/clie
nt.rb:129:in `get_token': OAuth2::Error (OAuth2::Error)
from /home/ec2-user/.rvm/gems/ruby-1.9.3-p0#samples/gems/oauth2-0.5.2/li
b/oauth2/strategy/auth_code.rb:29:in `get_token'
from oauth.rb:16:in `<main>'
Any help is greatly appreciated as I have spent more than a day while trying to sort this out.
Have you tried to put as redirect_uri instead of localhost:3000 your real IP address ex. 231.61.233.57:3000? Additionally you could try to use ssh tunneling for testing purposes so your localhost application will be available worldwide. Check this out http://progrium.com/localtunnel/ .
When you will get ip address from this tool try to set redirect_uri param to it.

Invalid OAuth tokens

I am using rforce gem and oauth2 login system for my SFDC app.
I am trying to login through Oauth2 but I get Invalid OAuth tokens error. Here is my code
access_token = oauth_client.web_server.get_access_token(params[:code], :redirect_uri => oauth_redirect_uri, :grant_type => 'authorization_code')
access_token is an OAuth2::AccessToken object
oauth = {
:consumer_key => '3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx3vxxxxxxxxxxxxxxxN',
:consumer_secret => '7xxxxxxxxxxx291xxxxxxx1',
:access_token => access_token.token,
:access_secret => '7xxxxxxxxxxx291xxxxxxx1',
:login_url => 'https://login.salesforce.com/services/OAuth/u/20.0'
}
I think consumer_secret and access_secret are same. If not, then what is access_secret and where could I find it?
I am using oauth2 -v 0.4.1 and rforce -v 0.8.1
What you are using here is Oauth1. In Oauth 2 there is only access_token and refresh_token. There is no access_secret any more.
I think this article will help you:
http://wiki.developerforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com

Resources