I've registered my mobile app (Sencha Touch) with Twitter and I have the appropriate keys to access version 1.1 of the API. Now I'm writing a web service to provide the JSON back to my mobile app. Here is what I have so far based on the ruby example provided by Twitter on this page.
require 'oauth'
class Twitter
def initialize
#consumer_key = "omitted"
#consumer_secret = "omitted"
#access_token = "omitted"
#access_token_secret = "omitted"
end
def pull_tweets(query)
authorized_token = prepare_access_token(#access_token, #access_token_secret)
response = authorized_token.request(:get, query)
end
private
def prepare_access_token(oauth_token, oauth_token_secret)
consumer = OAuth::Consumer.new(#consumer_key, #consumer_secret, { site: "https://api.twitter.com/", scheme: :header })
token_hash = { oauth_token: oauth_token, oauth_token_secret: oauth_token_secret }
access_token = OAuth::AccessToken.from_hash(consumer, token_hash)
return access_token
end
end
query = "https://api.twitter.com/1.1/statuses/home_timeline.json"
response = Twitter.new.pull_tweets(query)
p response
When I run this code I get #<Net::HTTPBadRequest 400 Bad Request readbody=true> as a response. After doing some research I found that this could be one of four things.
My authentication details are wrong
I'm being rate limited
Ruby is not formatting the query string properly (more details)
The query I'm using is wrong
I don't think I'm being rate limited because I've never managed to get a response, and I don't know how to check if I'm authenticating properly. Any help is much appreciated.
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'm using Ruby starting from the "hello world" example. Hello world works find. I'm trying to get this GET to work:
GET /projects/192372431230306/tasks?opt_fields=id,assignee,due_on,name,notes&limit=10&completed_since=now
It works exactly as expected in the Asana API explorer.
I'm using the same URI in my code:
uri = URI.parse("https://app.asana.com/api/1.0/projects/192372431230306/tasks?opt_fields=id,assignee,due_on,name,notes&limit=10&completed_since=now")
It still returns ID and Name correctly, but it's not what I want.
I can't see why it works in the explorer but not in the GET request. I am using the personal token and the explorer uses OAuth.
My personal token is set correctly before this code. I can create tasks, get projects, get tasks. I just can't more fields in this query like the API explorer.
Added Code:
uri = URI.parse("https://app.asana.com/api/1.0/projects/192372431230306/tasks?opt_fields=id,assignee,due_on,name,notes&limit=10&completed_since=now")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
# set up the request
header = {
"Content-Type" => "application/json"
}
req = Net::HTTP::Get.new(uri.path, header)
req.basic_auth(personal_access_token, '')
res = http.start { |http| http.request(req) }
body = JSON.parse(res.body)
puts "projects: #{body['data']}"
There isn't quite enough code here to know what's wrong. It sounds like your code is working to some degree, but maybe there's something different between using a personal token as opposed to OAuth. According to the Asana API documentation:
Personal Access Tokens should be used similarly to OAuth access tokens when accessing the API, passing them in the Authorization header:
curl -H "Authorization: Bearer ACCESS_TOKEN" https://app.asana.com/api/1.0/users/me
So in addition to the URL, you need to use the correct headers. I'm not sure what HTTP library you use, but here's how I would do it with HTTParty:
require 'uri'
require 'httparty'
uri = URI.parse("https://app.asana.com/api/1.0/projects/192372431230306/tasks?opt_fields=id,assignee,due_on,name,notes&limit=10&completed_since=now")
task = HTTParty.get(uri,
:headers =>
{'Authorization' => "Bearer ${ENV[ACCESS_TOKEN]}"}
).parsed_response
If you put your personal access token in the ACCESS_TOKEN environment variable, that should correctly authenticate you for the request.
Still, it seems like there's something else missing if you can get all the fields. Maybe your personal access token is associated with a different account than your OAuth access token? It might help to check the results of /users/me/ route?
I'm trying to get my GPS data from the Waze app using the rest-client lib. I'm basicly trying to fake a login via the website https://www.waze.com/. After login (you can use JohnDoeSpeedy228:gre#tStory92) when you visit https://www.waze.com/editor/, click on "Drives" after review the the network calls you'll get to see the raw JSON data.
I seem to have succesfully logged in but when making the request to return the list of all my drives it returns the following
{"users"=>{"objects"=>[]}, "archives"=>{"totalSessions"=>0, "objects"=>[]}}
It should return something like this:
{
"users":{
"objects":[
]
},
"archives":{
"totalSessions":1,
"objects":[
{
"id":<REDACTED>,
"userID":<REDACTED>,
"existingRoadMeters":2839,
"newRoadMeters":0,
"totalRoadMeters":2839,
"startTime":1456996197000,
"endTime":1456996636000,
"hasFullSession":true
}
]
}
}
Here's what I'm trying:
require 'rest-client'
require 'json'
GET_CSRF_URL = "https://www.waze.com/login/get"
SESSION_URL = "https://www.waze.com/login/create"
SESSION_LIST_URL = "https://www.waze.com/Descartes-live/app/Archive/List"
SESSON_DATA_URL = "https://www.waze.com/Descartes-live/app/Archive/Session"
AUTH = {'user_id'=>'JohnDoeSpeedy228','password'=>'gre#tStory92'}
req = RestClient.get(GET_CSRF_URL)
csrfhash = req.cookies
csrfhash['editor_env'] = 'row'
headers = {'X-CSRF-Token'=>csrfhash['_csrf_token']}
log = RestClient::Request.execute(
method: :post,
url: SESSION_URL,
cookies: csrfhash,
headers: headers,
payload: AUTH
)
ses = RestClient::Request.execute(
method: :get,
url: SESSION_LIST_URL,
cookies: log.cookies,
payload: {'minDistance'=>1000,'count'=>50, 'offset'=>0}
)
puts JSON.parse(ses)
Am I doing something wrong?
My guess is that you are confusing two accounts. Are you sure you logged a drive while logged in as JohnDoeSpeedy228? If there are no sessions from that user when logged into the site manually, I wouldn't expect the code to work either.
We can't find any of your drives.
Have you started driving with the Waze app yet? If so, please make sure you logged into the Map Editor with the same credentials you use in the app.
im new to ruby and trying to play a bit with Twitters API. I got my keys from twitter dev site and set their permissions to 'read, write and access direct messages'. I then tried to use some code found on codecademy to retrieve status code but got 401 error (replaced keys with X). The weird things is that this code in codecademy retrieves 200 status code, so im thinkings is something in my computer:
require 'rubygems'
require 'oauth'
consumer_key = OAuth::Consumer.new(
"X",
"X")
access_token = OAuth::Token.new(
"X",
"X")
# All requests will be sent to this server.
baseurl = "https://api.twitter.com"
# The verify credentials endpoint returns a 200 status if
# the request is signed correctly.
address = URI("#{baseurl}/1.1/account/verify_credentials.json")
# Set up Net::HTTP to use SSL, which is required by Twitter.
http = Net::HTTP.new address.host, address.port
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
I also tried using twitters gem (adding of course the needed keys) and this time i get the following error Timestamp out of bounds (Twitter::Error::Unauthorized)
require 'rubygems'
require 'twitter'
Twitter.configure do |config|
config.consumer_key = YOUR_CONSUMER_KEY
config.consumer_secret = YOUR_CONSUMER_SECRET
config.oauth_token = YOUR_OAUTH_TOKEN
config.oauth_token_secret = YOUR_OAUTH_TOKEN_SECRET
end
Twitter.update("I'm tweeting with #gem!")
I'm running ruby 1.9.3p429.
Any help would be more than appreciated.
I have been having your same issues and looking at oauth docs I have found the following:
Make a regular GET request using AccessToken:
#response = #token.get('/people')
#response = #token.get('/people', { 'Accept'=>'application/xml' })
You will find more details here if you are curious: http://oauth.rubyforge.org/rdoc/classes/OAuth/AccessToken.html
Anyhow here is my code:
def prepare_access_token()
#opts = {
'oauth_token' => 'TOKEN',
'oauth_token_secret' => 'TOKEN_SECRET',
'api_key' => 'API_KEY',
'api_secret' => 'API_SECRET'
}
consumer = OAuth::Consumer.new("#{#opts['api_key']}", "#{#opts['api_secret']}",
{ :site => "http://api.twitter.com",
:scheme => :header
})
# now create the access token object from passed values
token_hash = { :oauth_token => "#{#opts['oauth_token']}",
:oauth_token_secret => "#{#opts['oauth_token_secret']}"
}
access_token = OAuth::AccessToken.from_hash(consumer, token_hash )
return access_token
end
#here is your url
call_url = "https://api.twitter.com/1.1/statuses/home_timeline.json"
uri = URI.encode(call_url)
# Exchange our oauth_token and oauth_token secret for the AccessToken instance.
access_token = prepare_access_token()
# use the access token as an agent to get the home timeline
response = access_token.get(uri)
This worked for me. If you have feedback feel free to share it :)
I was having the same issue yesterday, since a couple days ago. What happened was that I lived overseas for a while, and I had my region set up to region X, but had manually changed my clock to my current one. As soon as I set up my current region and sync'd with the internet timezone, the error was gone.
I had the same problem (401) I resolved it by going into the app in twitter and regenerating the consumer key and Consumer Secret, which is very easy as there is a button to do it, using the new values stopped my 401 errors. Hope this helps someone.
I am trying to implement facebook authentication for an app with warden, after the user allows facebook auth and redirects to my app callback with the token I get a 400 while consuming the api. My warden strategy is this:
class Facebook < Warden::Strategies::Base
def client
#client ||= OAuth2::Client.new MyApp::Facebook::AppID, MyApp::Facebook::AppSecret, :site => 'https://graph.facebook.com'
end
def params
#params ||= Rack::Utils.parse_query(request.query_string)
end
def authorize_url
client.web_server.authorize_url :redirect_uri => request.url, :scope => 'email,publish_stream'
end
def authenticate!
throw(:halt, [302, {'Location' => authorize_url}, []]) unless params['code']
facebook = client.web_server.get_access_token params['code'], :redirect_uri => request.url
rescue OAuth2::HTTPError => e
puts e.response.body
end
end
Strategies.add :facebook, Facebook
The result of printing the response body is this:
{"error":{"type":"OAuthException","message":"Error validating client secret."}}
I am pretty shure the app id and app secret are the ones provided by FB.
Thanks.
I've seen that error message many times. Here are the things I would double check:
your domain is the same as what you listed in the facebook callback url
the app id is correct (actually print this out on a page, sometimes y
the app secret is correct
Add redirect_uri while creating the object of facebook that will fix the issue.
Redirect the user to https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL
After user click allow, it'll hit our Redirect Uri
At that point we'll get the code and we need to do a server side HTTP Get to the following Url to exchange the code with our oAuth access token:
https://graph.facebook.com/oauth/access_token?
client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&
client_secret=YOUR_APP_SECRET&code=THE_CODE_FROM_ABOVE
Now at step 3, I kept on getting Http 400 response back.
So after some research, I found out that on that redirect_uri that we submitted on step 3 doesn't do anything but validate the request. Thus, the value need to match with step 2.
I also get the same error and i resolved by doing as below:
double check your client_id, client_secret, redirect_uri.
Add Accept: "application/json" header to thye request
fetch(
`https://graph.facebook.com/v15.0/oauth/access_token?client_id=${process.env.FACEBOOK_APP_ID}&redirect_uri=${process.env.FACEBOOK_REDIRECT_URI}&client_secret=${process.env.FACEBOOK_APP_SECRET}&code=${code}`,
{
method: "GET",
headers: {
Accept: "application/json",
},
}
)