Undefined method `OAuth' when making HTTP request to Twitter api - ruby-on-rails

I'm getting the following OAuth error when trying to make a request to the Twitter streaming api:
"#NoMethodError: undefined method `OAuth' for #TwitterMoment:0x007fa081d821f0"
def query
authorisation_header = OAuth oauth_consumer_key=ENV["oauth_consumer_key"], oauth_nonce=ENV["oauth_nonce"], oauth_signature=ENV["oauth_signature"], oauth_signature_method=ENV["oauth_signature_method"], oauth_timestamp=ENV["oauth_timestamp"], oauth_token=ENV["oauth_token"], oauth_version=ENV["oauth_version"]
response = HTTParty.get("https://stream.twitter.com/1.1/statuses/filter.json?locations=-#{#bounds}", headers: {"Authorization" => authorisation_header})
end
OAuth is included in my gemfile.
Any ideas would be very much appreciated! This is my first Stack Overflow question :)

You're using OAuth here as a function/method, but that method doesn't exist. There's no def OAuth(...) anywhere in the oauth gem, so it explodes and gives you that NoMethodError.
Judging from the Header example at the bottom of this question, I think you've confused the header string for Ruby code.
Instead, you either need to make the string yourself (a bit annoying to do safely), or use the OAuth gem's methods (API) to do so.
Here's an example from the OAuth github repo:
consumer = OAuth::Consumer.new(
options[:consumer_key],
options[:consumer_secret],
:site => "http://query.yahooapis.com"
)
access_token = OAuth::AccessToken.new(consumer)
response = access_token.request(
:get,
"/v1/yql?q=#{OAuth::Helper.escape(query)}&format=json"
)
rsp = JSON.parse(response.body)
pp rsp
This example may work for you (I'm not able to test it locally here, sorry):
def query
consumer = OAuth::Consumer.new(
ENV["oauth_consumer_key"],
ENV["oauth_consumer_token"],
site: "https://stream.twitter.com"
)
access_token = OAuth::AccessToken.new(consumer)
response = access_token.request(
:get,
"/1.1/statuses/filter.json?locations=-#{OAuth::Helper.escape(#bounds)}"
)
response = JSON.parse(response.body)
pp response # Just a bit of debug printing for the moment; remove this later.
response
end
An addendum:
Usually I might have directed you to use an existing Twitter client gem, such as https://github.com/sferik/twitter, but in this case it looks like they haven't implemented the Moments API yet.

Related

Cause of google vision API HTTP Forbidden error? Ruby (Rails)

I have been trying to get the google vision API to work in my rails application but keep getting a Net::HTTPForbidden response. I'm not really sure what is causing it since everything I have seems to be setup properly, I've tried generating new keys and still get the same error, any help would be appreciated. I replaced my API key with 'XXXXX_MY_API_KEY_XXXXX' in this post for obvious reasons, so that is not the issue, also have tried directly pasting in an image url in place of the 'img_url' so I don't think that that is related to the issue either.
require 'net/http'
require 'uri'
require 'json'
def transcribe(img_url)
uri = URI.parse('https://vision.googleapis.com/v1/images:annotate?key=' + 'XXXXX_MY_API_KEY_XXXXX')
request = Net::HTTP::Post.new(uri)
request.content_type = 'application/json'
request.body = JSON.dump(
'requests' => [
{
'image' => {
'source' => {
'imageUri' => img_url
}
},
'features' => [
{
'type' => 'TEXT_DETECTION',
'maxResults' => 1,
'model' => 'builtin/latest'
}
]
}
]
)
req_options = {
use_ssl: uri.scheme == 'https'
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
p response
p response.code
p response.body
end
Ok, so after hours of messing around with this I finally figured out the issue. When you first try to use the api they will return a link to you that you have to visit to activate the specific API (vision in my case), I could not find this page through the ui on the google cloud control panel, only through the link. Even though the API key was active and unrestricted with billing setup it would not function without activating the specific API. Because I had commented out the response code/body I was only getting the status code for my API call and was not seeing the rest of the response, preventing me from finding the proper activation link.
This was a massive lapse of judgement on my part, hopefully this will help anyone who runs into a similar issue or is looking to integrate google vision API into a rails app and stumbles upon this thread, the code shown above works totally fine and is a much simpler approach to using the API when compared to the client library, just make sure that you have the specific API that you want to use enabled. Just because the API key is not restricted does not mean that you can simply use any of their APIs, I made sure to 'fix' (uncomment) the code I posted for anyone else who may find it useful.

Rails - Slack API OAuth Access - invalid_client_id

I'm building Slack integration for my Ruby on Rails application and I'm trying to get an access_token from the Slack API for my Slack App when a user clicks the Add to Slack button.
From Postman, I can successfully post the following:
https://slack.com/api/oauth.access?client_id=idgoes.here&client_secret=secretgoeshere&code=12345&pretty=1
However, within Rails I always get a response with invalid_client_id, regardless of the way I call the API. I have checked my ID is correct (a lot) and tried regenerating it, but I don't think that is the issue due to the postman success.
Within my get_oauth_access_token method I have tried the following implementations:
1.
rc = JSON.parse(HTTP.post('https://slack.com/api/oauth.access',
params: {
client_id: 'idgoes.here',
client_secret: 'secretgoeshere',
code: '12345'
}))
2.
response = Excon.post('https://slack.com/api/oauth.access',
headers: { 'Content-Type' => 'application/json; charset=utf-8' },
user: client_id, password: client_secret,
body: oauth_request_body.to_json)
Any implementation I try always ends up getting a invalid_client_id response.
I'm aware it may be something to do with environment config, but I'm not sure what would be helpful to debug, so please let me know what other information I can share. I'm running on localhost.
Update:
I just found out that many (maybe all) of the Slack APIs do not accept a JSON format body (which seems crazy seeing as they send a response in JSON.
Make sure to use x-www-form-urlencoded format body on your request or it will not work properly.
"Content-Type" => "application/x-www-form-urlencoded"
I use oauth2 gem to authorize. So I was able to get this to work by reading the slack documentation and using oauth2 in my controller:
class OauthController < ApplicationController
def authorize
options = {
site: 'https://slack.com/oauth/authorize'
}
client ||= OAuth2::Client.new(
'client-id',
'client-secret',
options
)
params = {
scope: 'incoming-webhook, commands',
redirect_uri: 'https://localhost:3000/oauth/callback'
}
redirect_to client.auth_code.authorize_url(params)
end
def authorize_callback
puts params["code"]
redirect_to root_url
end
end
Routes file:
get '/authorize', to: 'oauth#authorize'
get '/oauth/callback', to: 'oauth#authorize_callback'
Don't forget to set your callback url at Oauth settings on api.slack.com, I used localhost for testing purposes as you can see.

Issues sending a POST via Net::HTTP to a Battle.Net Community API End-Point (OAuth 2)

Versions:
Ruby 2.2.4
Rails 4.2
Omniauth-oauth2 1.3.1
Omniauth-bnet 1.1.0
Issue:
Trying to complete the authorization and token request process to Blizzard's Battle Net Community API. While I can get the authorization_code returned, when I attempt to construct a POST back to the token endpoint it keeps telling me that its an invalid request/internal server error or just returns back the following object: <Net::HTTPFound 302 Found readbody=true> which has a blank string for a response body. Details for how Blizzard recommends handling the OAuth 2 process are located here: Battle.net OAuth 2 Guide. The omniauth-bnet gem is the one Blizzard suggested but doesn't seem to handle the entire OAuth authorization and token process but I'll freely admit I'm brand new when it comes to anything OAuth related so I could be wrong.
Any help you all can provide would be very welcome!
Controller Code:
def index
client_id = ENV[BNET_CLIENT_ID]
client_secret = ENV[BNECT_CLIENT_SECRET]
uri = URI('https://us.battle.net/auth/token?
redirect_uri=https%3A%2F%2f127%2f0%2f0%2f1%3A3001%2Fauth%2Fbnet%2Fcallback
&grant_type=authorization_code
&code=' + params["code"])
req = Net::HTTP::Post.new(uri)
req.basic_auth(client_id, client_secret)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') {|http| http.request(req)}
#bnet_response = res.body
end
Process:
Click link on index.html page which triggers the authorization process to start by sending a GET request to https://us.battle.net/oauth/authorize?client_id=&client_secret=&redirect_uri=&response_type=code
BNet API accepts the request and redirects user to Battle.Net Login screen
User authorizes app and is redirected (via redirect_uri) back to the index page with query parameters for the authorization_code
My app SHOULD make a POST request using the controller code above and the response should contain the actual access token.
This is just some hastily cobbled together code while I'm trying to get this working. I'll clean it up once I get over this little speed bump. I wouldn't hardcode the URI and such normally, just getting frustrated with things.
Things I've tried:
Using Rest-Client : There's a callback redirect that it can't handle apparently
Testing Postman : When using their OAuth 2 Authorization it works just fine, also works fine if I use Postman to get the authorization code (GET) and token (POST), so I'm assuming things work on the Blizz side and my code just sucks.
config/routes.rb
Rails.application.routes.draw do
root to: 'pages#index'
get '/auth/:provider/callback', to: 'pages#index'
end
I'm not familiar with the Battle.net API, however reading your process it seems you are getting an authorization code back from the redirect in the form of a query parameter (accessed by params[:code]) correct?
You also mention that this works using Postman indicating the flaw must be somewhere in the code.
I would suggest using the following snippet and let me know if it works. I would encourage using puts url after url = ... code to ensure the URI looks exactly as you want it (and has the correct code, client id, secret, redirect_uri).
require 'uri'
require 'net/http'
# Remember to change the redirect uri to match yours
redirect_uri = 'https://my-domain-name.com/auth/bnet/callback'
# Double check the environment variable names for BNET ID / Secret
url = URI("https://us.battle.net/oauth/token?redirect_uri=#{redirect_uri}&code=#{params[:code]}" \
"&grant_type=authorization_code&scope=wow.profile&client_id=#{ENV['BNET_CLIENT_ID']}" \
"&client_secret=#{ENV['BNET_CLIENT_SECRET']}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_body
Ensure your domain is accessible over https as this seems to be required.

What are some guidelines for creating HTTP requests in a Rails app?

I am relatively new to writing code against REST APIs. It is possible I am analyzing the wrong problem here, so feel free to give big picture advice. The other twist is that the API I want to use is not yet configured, so I can't test.
I need to write some Rails code to create webhooks on the Jive API. Jive's docs show how to register the webservice via a curl request. I want to build the code as an admin function of my app in case we need to recreate the webhook for any reason.
Here are the Jive Docs.
Based on this guide, I'm thinking I need something like (I expect this example to sent a POST request to "sample.jiveon.com/api/core/v3/webhooks"):
#host = "sample.jiveon.com/api/core/v3"
#port = "443"
#post_ws = "/webhooks"
#payload ={
"events" => "document",
"callback" => "my_app/jive_listener",
"object" => "my/jive/space"
}.to_json
def post
req = Net::HTTP::Post.new(#post_ws, initheader = {'Content-Type' =>'application/json'})
req['Authorization'] = "Bearer my_key"
req.body = #payload
response = Net::HTTP.new(#host, #port).start {|http| http.request(req) }
end
end
Thanks.
It would be better to use gem like 'rest-client(https://github.com/rest-client/rest-client)'
Above gem does the many stuff, which you might be doing manually using bare ruby library. It depends on need of yours.

OAuth call for a request token yields a 404 error

I am having an incredibly difficult time getting the OAuth gem working correctly for the Flickr API. I'm trying to generate a request token using this code:
user_oauth = OAuth::Consumer.new(consumer_key, consumer_secret, :site => "https://secure.flickr.com/services")
request_token = user_oauth.get_request_token(:oauth_callback => callback_url)
Whenever I run this code it throws an exception "OAuth::Unauthorized (404 Not Found)" on the call to .get_request_token.
I got my end point from: http://www.flickr.com/services/api/misc.overview.html
My OAuth gem is using the default request_token path, which should work with Flickr according to: http://www.flickr.com/services/api/auth.oauth.html#request_token I also tried using the endpoint that this link uses (http://www.flickr.com/services)
When I call .request_token_url on my OAuth::Consumer object, it returns "https://secure.flickr.com/services/oauth/request_token", which I can access in my browser. Thinking that the flickr API might only work with GET requests, I changed the OAuth method to GET and it still didn't work.
I've used this exact same code on different APIs before and it worked, so I'm not really sure what to do at this point. Any help would be appreciated!
I had the same problem. Request_token_url method returns right url, but I watch on true requested url by wireshark and there was www.flickr.com/oauth/request_token.. So it needs to move /services path from :site option into paths options.
This code works for me, now:
consumer = OAuth::Consumer.new(key, secret,
:site => "http://www.flickr.com",
:request_token_path => '/services/oauth/request_token',
:authorize_path => '/services/oauth/authorize',
:access_token_path => '/services/oauth/access_token')
request_token = consumer.get_request_token
I was having the same issue, but my callback url was "oob" which they say to use if you don't have access to a browser. Anyway I took the quotes off the oob and it works now.

Resources