I want to make oAuth request in Ruby. I skimmed some examples but none of them used oauth_token_secret and oauth_token to make a request, they only used consumer_key and consumer_secret to get oauth_token_secret and oauth_token. But I already have oauth_token_secret and oauth_token.
For example, this one I tried to use
require 'rubygems'
require 'oauth'
consumer = OAuth::Consumer.new(consumer_key, consumer_secret,
{
:site=> "https://www.google.com",
:scheme=> :header,
:http_method=> :post,
:request_token_path => "/accounts/OAuthGetRequestToken",
:access_token_path => "/accounts/OAuthGetAccessToken",
:authorize_path=> "/accounts/OAuthAuthorizeToken",
:signature_method=>"RSA-SHA1"},
# :private_key_file=>PATH_TO_PRIVATE_KEY
)
request_token = consumer.get_request_token()
puts "Visit the following URL, log in if you need to, and authorize the app"
puts request_token.authorize_url
puts "When you've authorized that token, enter the verifier code you are assigned:"
verifier = gets.strip
puts "Converting request token into access token..."
access_token=request_token.get_access_token(:oauth_verifier => verifier)
puts "access_token.token --> #{access_token.token}" # But I initially have it
puts "access_token.secret --> #{access_token.secret}" # But I initially have it
In my case, there are 4 secret keys:
consumer_key = "anonymous"
consumer_secret = "anonymous"
oauth_token_secret = "fdsfdsfdfdsfds"
oauth_token = "fdsfdsfdfdsfdsdsdsdsdsdsds"
So what I need to do is, to make a API request to the certain url with some additional get parameters and oAuth token and to get the answer.
How do I do that in Ruby?
#!/usr/bin/env ruby
require 'rubygems'
require 'oauth'
require 'json'
You need to get your access_token (OAuth::AccessToken).
# Initialisation based on string values:
consumer_key = 'AVff2raXvhMUxFnif06g'
consumer_secret = 'u0zg77R1bQqbzutAusJYmTxqeUpWVt7U2TjWlzbVZkA'
access_token = 'R1bQqbzYm0zg77tAusJzbVZkAVt7U2T'
access_token_secret = 'sVbVZkAt7U2TjWlJYmTxqR1bQqbzutAuWzeUpu0zg77'
#consumer = OAuth::Consumer.new(consumer_key, consumer_secret, {:site=>'http://my.site'})
accesstoken = OAuth::AccessToken.new(#consumer, access_token, access_token_secret)
Once you have your OAuth::AccessToken object, you do :
json_response = accesstoken.get('/photos.xml')
# or
json_response = accesstoken.post(url, params_hash)
etc.
The response is a json object. To read it, you can do :
response = JSON.parse(json_response.body)
# which is a hash
# you just access content like
id = response["id"]
Related
Now I took a sample code of Twitter v2 API from this link. This sample code shows how OAuth and twitter v2 API work for positng a tweet. It works fine with my consumer key and consumer secret.
And I want to simplify the code like below. It assumes that the access token and access token secret are already known and it skips the process of user's approval, like providing the URL that provides PIN.
require 'typhoeus'
require 'json'
consumer_key = CONSUMER_KEY
consumer_secret = CONSUMER_SECRET
token = ACCESS_TOKEN
token_secret = ACCESS_TOKEN_SECRET
consumer = OAuth::Consumer.new(consumer_key, consumer_secret, :site => 'https://api.twitter.com')
options = {
:method => :post,
headers: {
"User-Agent": "v2CreateTweetRuby",
"content-type": "application/json"
},
body: JSON.dump("Hello, world!")
}
create_tweet_url = "https://api.twitter.com/2/tweets"
request = Typhoeus::Request.new(create_tweet_url, options)
access_token = OAuth::Token.new(token, token_secret)
oauth_params = {:consumer => consumer, :token => access_token}
oauth_helper = OAuth::Client::Helper.new(request, oauth_params.merge(:request_uri => create_tweet_url))
request.options[:headers].merge!({"Authorization" => oauth_helper.header}) # Signs the request
response = request.run
puts response
Then, I see the below error message.
ruby test_tweet.rb
/usr/local/lib/ruby/gems/3.1.0/gems/oauth-0.5.10/lib/oauth/request_proxy.rb:18:in `proxy': Typhoeus::Request (OAuth::RequestProxy::UnknownRequestType)
from /usr/local/lib/ruby/gems/3.1.0/gems/oauth-0.5.10/lib/oauth/signature.rb:12:in `build'
from /usr/local/lib/ruby/gems/3.1.0/gems/oauth-0.5.10/lib/oauth/signature.rb:23:in `sign'
from /usr/local/lib/ruby/gems/3.1.0/gems/oauth-0.5.10/lib/oauth/client/helper.rb:49:in `signature'
from /usr/local/lib/ruby/gems/3.1.0/gems/oauth-0.5.10/lib/oauth/client/helper.rb:82:in `header'
from test_tweet.rb:28:in `<main>'
When I used irb and tried step by step, this error happens at oauth_helper.header. As this is the first time to use OAuth API, I may be making some easy mistakes. Does anybody find anything wrong in my code?
I confirmed that my access token and access token secret work at https://web.postman.co/.
Thanks.
You need to insert
require 'oauth/request_proxy/typhoeus_request'
and your code may complete task you desire.
Other lines looks good to me!
In oauth/request_proxy.rb, oauth library check class of request object.
https://github.com/oauth-xx/oauth-ruby/blob/master/lib/oauth/request_proxy.rb
return request if request.is_a?(OAuth::RequestProxy::Base)
klass = available_proxies[request.class]
# Search for possible superclass matches.
if klass.nil?
request_parent = available_proxies.keys.find { |rc| request.is_a?(rc) }
klass = available_proxies[request_parent]
end
raise UnknownRequestType, request.class.to_s unless klass
By requiring 'oauth/request_proxy/typhoeus_request', Typhoeus::Request inherits OAuth::RequestProxy::Base and raising UnknownRequestType error can be avoided.
https://github.com/oauth-xx/oauth-ruby/blob/master/lib/oauth/request_proxy/typhoeus_request.rb
I am trying to find all the freebusy times from my primary calendar using the "query_freebusy" method but I am receiving a "not found" error as a response
I admit I am a novice coder at best, but so far I've been using much of the code from the quickstart-example in the google calendar API documentation to authorize my requests, as well as code from another stack overflow page regarding the query_freebusy method.
My code is as follows:
require 'google/apis/calendar_v3'
require 'googleauth'
require 'googleauth/stores/file_token_store'
require 'date'
require 'fileutils'
require 'pry'
require 'pp'
OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'.freeze
APPLICATION_NAME = 'Google Calendar API Ruby Quickstart'.freeze
CREDENTIALS_PATH = 'credentials.json'.freeze
TOKEN_PATH = 'token.yaml'.freeze
SCOPE = Google::Apis::CalendarV3::AUTH_CALENDAR
def authorize
client_id = Google::Auth::ClientId.from_file(CREDENTIALS_PATH)
token_store = Google::Auth::Stores::FileTokenStore.new(file: TOKEN_PATH)
authorizer = Google::Auth::UserAuthorizer.new(client_id, SCOPE, token_store)
user_id = 'default'
credentials = authorizer.get_credentials(user_id)
if credentials.nil?
url = authorizer.get_authorization_url(base_url: OOB_URI)
puts 'Open the following URL in the browser and enter the ' \
"resulting code after authorization:\n" + url
code = gets
credentials = authorizer.get_and_store_credentials_from_code(
user_id: user_id, code: code, base_url: OOB_URI
)
end
credentials
end
service = Google::Apis::CalendarV3::CalendarService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = authorize
calendar_id = 'primary'
body = Google::Apis::CalendarV3::FreeBusyRequest.new
body.items = [calendar_id]
body.time_min = "2019-04-28T00:00:00-00:00"
body.time_max = "2019-04-30T00:00:00-00:00"
response = service.query_freebusy(body)
puts response.to_json
The response I get is:
{"calendars":{"":{"busy":[],"errors":[{"domain":"global","reason":"notFound"}]}},"kind":"calendar#freeBusy","timeMax":"2019-04-30T00:00:00.000+00:00","timeMin":"2019-04-28T00:00:00.000+00:00"}
I have 5 events on that calendar between that time frame, but none show up in the response.
I have a google Oauth that will make the user authorize when a user goes to my webpage, however I only want them to have to authorize the app so that I can get their access and refresh tokens when they go to certain page to enter a google api information.Google is making them authorize no matter what route they are on any ideas on how to stop this.Ruby wont let me any of this in a route.
def user_credentials
# Build a per-request oauth credential based on token stored in
session
# which allows us to use a shared API client.
#authorization ||= (
auth = settings.authorization.dup
auth.redirect_uri = to('/oauth2callback')
auth.update_token!(session)
auth
)
end
configure do
Google::Apis::ClientOptions.default.application_name = 'Get Login
info for Google Ad Exchange'
Google::Apis::ClientOptions.default.application_version = '1.0.0'
client_secrets = Google::APIClient::ClientSecrets.load
authorization = client_secrets.to_authorization
authorization.scope =
'https://www.googleapis.com/auth/adexchange.seller.readonly'
set :authorization, authorization
end
before do
# Ensure user has authorized the app
unless user_credentials.access_token || request.path_info =~
/^\/oauth2/
redirect to('/oauth2authorize')
end
end
after do
# Serialize the access/refresh token to the session and credential
store.
# We could potentially need to pull back the client_id and
client_secret as well and add them to the dynamo database.
# session[:client_id] = user_credentials.client_id
# session[:client_secret] = user_credentials.client_secret
session[:access_token] = user_credentials.access_token
session[:refresh_token] = user_credentials.refresh_token
session[:expires_in] = user_credentials.expires_in
session[:issued_at] = user_credentials.issued_at
end
get '/oauth2authorize' do
# Request authorization
redirect user_credentials.authorization_uri.to_s, 303
end
get '/oauth2callback' do
# Exchange token
user_credentials.code = params[:code] if params[:code]
user_credentials.fetch_access_token!
redirect to('/')
end
Figured it out, meant to post way earlier but had an alert on this post so i figured id update to what we did to ake it work.
get '/googleauth' do
salesforce_username = params[:salesforce_username] || ''
unless session.has_key?(:credentials)
redirect to('/oauth2callback')
end
client_opts = JSON.parse(session[:credentials])
auth_client = Signet::OAuth2::Client.new(client_opts)
redirect to('/googleadx')
end
get '/oauth2callback' do
client_secrets = Google::APIClient::ClientSecrets.load
auth_client = client_secrets.to_authorization
auth_client.update!(
:scope => 'https://www.googleapis.com/auth/adexchange.seller.readonly',
:redirect_uri => url('/oauth2callback'))
if request['code'] == nil
auth_uri = auth_client.authorization_uri.to_s
redirect to(auth_uri)
else
auth_client.code = request['code']
auth_client.fetch_access_token!
session[:access_token] = auth_client.access_token
session[:refresh_token] = auth_client.refresh_token
session[:expires_in] = auth_client.expires_in
session[:issued_at] = auth_client.issued_at
auth_client.client_secret = nil
session[:credentials] = auth_client.to_json
redirect to('/googleadx')
end
end
get '/googleadx' do
# configure()
if params[:username]
successmessage = params[:username] + "'s credentials added successfully."
else
message = ''
end
salesforce_username = session[:salesforce_username] || ''
access_token = session[:access_token]
refresh_token = session[:refresh_token]
googleDollarLimit = ''
erb :googleadx, locals: {message: message, successmessage: successmessage, salesforce_username: salesforce_username, access_token: access_token, refresh_token: refresh_token, googleDollarLimit: googleDollarLimit}
end
I'm trying to send a request via Typhoeus to Bitbucket's API using Ruby, and I'm doing so with credentials from the "OAuth consumers" page - the consumer_key and consumer_secret. I can get the token just fine, but I get an error when trying to generate the header from the OAuth helper. Here's the relevant code (note that this is not Rails; I'm using Sinatra):
# oauth_token and oauth_token_secret are from a request to https://bitbucket.org/api/1.0/oauth/request_token
#consumer = OAuth::Consumer.new(
consumer_key,
consumer_secret,
)
#token = OAuth::Token.new(oauth_token, oauth_token_secret)
options = {
method: :post,
body: body.to_json
}
oauth_params = {:consumer => #consumer, :token => #token}
hydra = Typhoeus::Hydra.new
url = "https://api.bitbucket.org/2.0/repositories/..."
req = Typhoeus::Request.new(url, options)
oauth_helper = OAuth::Client::Helper.new(req, oauth_params.merge(:request_uri => url))
req.options[:headers].merge!({"Authorization" => oauth_helper.header})
The last line fails with a OAuth::RequestProxy::UnknownRequestType error. Basically what it's saying is that the OAuth RequestProxy doesn't understand the Typhoeus::Request object; from what I can see, it only has support for Net::HTTPGenericRequest and Hash. The Typhoeus documentation indicates that this should work, so it's possible I'm doing something wrong.
Alternatively, is there a better way to do this? Should I use a different request library? HTTParty doesn't have great support for auth headers like this. Thanks!
You need to explicitly require the RequestProxy.
require 'typhoeus'
require 'oauth'
require 'oauth/request_proxy/typhoeus_request'
How can I add post parameters to what I have right now:
#toSend = {
"nonce" => Time.now.to_i,
"command" => "returnCompleteBalances"
}.to_json
uri = URI.parse("https://poloniex.com/tradingApi")
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})
req.set_form_data({"nonce" => Time.now.to_i, "command" => "returnCompleteBalances"})
req['Key'] = '******-N4WZI2OG-******-10RX5JYR'
req['Sign'] = 'secret_key'
req.body = "[ #{#toSend} ]"
res = https.request(req)
puts "Response #{res.code} #{res.message}: #{res.body}"
These are the params I want to send:
"nonce" => Time.now.to_i,
"command" => "returnCompleteBalances"
Thank you.
It appears that you're trying to use Poloniex's trading API. If this is your primary goal, you might wish to consider using a library to handle the nitty-gritty details. For example:
https://github.com/Lowest0ne/poloniex
If your primary goal is not simply to use the API, but to use this as a learning experience, here are a few pointers:
The API documentation indicates that the API accepts form-encoded POST data (not JSON) but responds with JSON.
The key parameter ("Key") is like your user id. It allows Poloniex to understand who is attempting to make a request against the API.
The signature parameter ("Sign") is an HMAC generated from the contents of your secret key and the contents of your message (the encoded form data). This produces a sort of fingerprint that only you and Poloniex have the information to reproduce, giving some level of assurance that your request originated from the owner of the secret key. Of course, this assumes that your secret key is indeed only known by you.
I don't use the Poloniex exchange and cannot test this code, but I believe this is close to what you're attempting to accomplish:
require 'net/http'
require 'openssl'
secret = 'your-secret-key'
api_key = 'your-api-key'
uri = URI('https://poloniex.com/tradingApi')
http = Net::HTTP.new(uri.host)
request = Net::HTTP::Post.new(uri.request_uri)
form_data = URI.encode_www_form({:command => 'returnBalances', :nonce => Time.now.to_i * 1000 })
request.body = form_data
request.add_field('Key', api_key)
request.add_field('Sign', OpenSSL::HMAC.hexdigest( 'sha512', secret, form_data))
res = http.request(request)
puts res.body