Error with facebook access token - ruby-on-rails-3

My problem is on facebook callback url. I am using fbgraph gem on Rails 3.0.
I ask for extended permissions on my tab application. So in the callback I wait code parameter and access_token.
I extract this code from fbgraph official GIT repository.
def authorize
begin
#auth.client.authorization_code = params[:code]
#In access_token line should return me access__token but throw a error message (see below)
access_token = #auth.client.access_token! # => Rack::OAuth2::AccessToken
#facebook_user = FbGraph::User.me(access_token).fetch # => FbGraph::User
#MORE CODE WITHOUT IMPORTANCE
redirect_to :controller => "dashboard", :action => "index"
rescue Exception => e
logger.info(e.message)
end
end
Throw this error message:
Rack::OAuth::Client::Error # => #status = 400, Message => Missing redirect uri
Please I need help quickly. Excuse me and thanks in advance

I'm using the fb_graph gem which is similar. In order to get the access_token you also need to supply the callback URI - this is the fb_graph version:
client.redirect_uri = "http://your.callback.uri"
client.authorization_code = params[:code]
access_token = client.access_token!
Update:
Looking at the fbgraph gem documentation I think you need to replace these two lines:
#auth.client.authorization_code = params[:code]
access_token = #auth.client.access_token!
With this:
access_token = #auth.client.authorization.process_callback(params[:code], :redirect_uri => callback_url)
To be honest I looked at using the fbgraph gem but the documentation was so bad that I switched to fb_graph instead which is similar and actually has some useful examples in the documentation.

Related

How do I pass in the 'hd' option for OpenID Connect (Oauth2 Login) using the Google Ruby API Client?

The "Using Oauth 2.0 for Login" doc lists the 'hosted domain' parameter as a valid authentication parameter, but using the Google API Client for Ruby linked at the bottom I don't see how to pass it along with my request. Anyone have an example?
OK, wasn't perfect, but I just passed it to the authorization_uri attribute on the authorization object like so
client = Google::APIClient.new
client.authorization.authorization_uri(:hd => 'my_domain')
I still had trouble updating the Addressable::URI object to save the change (kept getting a "comparison of Array with Array failed" error), but this was good enough for me to use.
I couldn't get it to work using the Google::APIClient but managed to get it working using the OAuth2::Client like this
SCOPES = [
'https://www.googleapis.com/auth/userinfo.email'
].join(' ')
client ||= OAuth2::Client.new(G_API_CLIENT, G_API_SECRET, {
:site => 'https://accounts.google.com',
:authorize_url => "/o/oauth2/auth",
:token_url => "/o/oauth2/token"
})
...
redirect client.auth_code.authorize_url(:redirect_uri => redirect_uri,:scope => SCOPES,:hd => 'yourdomain.com')

Rails + Oauth + Tumblr

I came across an interesting issue with Tumblr's oauth implementation that I wanted to document for others. When ever i used the code below i received a "400 Bad Request", when I inspected the respose in wireshark I discovered this was coming back from tumblr "Out-of-band ("oob") callbacks are not supported by this implementation.". This is wwierd because my tumblr application has a call back field that I had explicitly set.
# Your tumblr details:
key = "Your Key"
secret = "Your Secret"
site = "http://www.tumblr.com"
# puts 'Setting up request'
#consumer = OAuth::Consumer.new(key, secret, { :site => site,
:request_token_path => '/oauth/request_token',
:authorize_path => '/oauth/authorize',
:access_token_path => '/oauth/access_token',
:http_method => :post
})
puts 'Asking for token, dies here.'
#request_token = #consumer.get_request_token()
puts 'Got Token Storing'
session[:request_token]=#request_token
puts 'Redirecting'
redirect_to #request_token.authorize_url
Turns out that call back field in tumblr's api isn't being taken into account.
you need to change this line:
#request_token = #consumer.get_request_token()
to be:
#request_token = #consumer.get_request_token(:oauth_callback => "http://192.168.2.115:5000/oauth/callback")
That seems to make it all work.

Deprecated offline_access on facebook with RoR

We have a problem in our RoR app. We are using a facebook authentication with omniauth, and searching the user friends with Koala. But lately, when we try to show a friend photo, we got this error:
Koala::Facebook::APIError in Homes#show
Showing /home/daniel/Homes/app/views/shared/_event.html.erb where line #19 raised:
OAuthException: Error validating access token: Session has expired at unix time 1328727600. The current unix time is 1328802133.
Extracted source (around line #19):
16: <img src="../assets/friends-icon.png" alt="User profile apicture" height="33" width="43">
17: <% if current_user %>
18: <% event.friends_in_event(#person).each do |f| %>
19: <%= link_to(image_tag(f.fb_picture, :size => "43x33"), person_path(f.id)) %>
20: <% end %>
21: <% end %>
22: </div>
The authentication works good, but facebook has already deprecated the offline_access option, that was working good, but now, we have this issue.
is It any way to extends the access_token?, or are there another solution?.
This is our omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, ENV['FB_KEY'], ENV['FB_SECRET'],
{ :scope => 'email,offline_access,user_photos,publish_stream',
:client_options => { :ssl => { :ca_path => "/etc/ssl/certs" } } }
end
And our koala.rb
Koala.http_service.http_options = {
:ssl => { :ca_path => "/etc/ssl/certs" }
}
Thanks in advance.
There are 2 solutions to this problem:
Extend the user's access token:
As per this article on the Facebook docs, you may request a 60-day extension on a user's access token. However, if the user does not return within that period, this method won't help you.
You can find a PHP code snippet to do this at this StackOverflow question.
To do this, send a post to this API endpoint: https://graph.facebook.com/oauth/access_token?client_id=APP_ID&client_secret=APP_SECRET&grant_type=fb_exchange_token&fb_exchange_token=EXISTING_ACCESS_TOKEN
Catch the OAuthException and request a new access token:
Facebook provides a PHP code snippet outlining this solution on their dev blog.
Basically, you follow these steps:
Make a call to the graph with the user's current access_token.
If the call succeeds, the access_token is fine. If it throws an OAuthException, redirect the user to https://www.facebook.com/dialog/oauth?client_id=APP_ID&redirect_uri=CALLBACK_URL
The user will be sent to that URL and then redirected to your CALLBACK_URL with a code in the parameters.
Send a post to the following URL with the code to obtain a new access_token: https://graph.facebook.com/oauth/access_token?client_id=APP_ID&redirect_uri=CALLBACK_URL&client_secret=APP_SECRET&code=CODE&display=popup
Read the post on their dev blog for more information.
Edit (adding example Ruby on Rails code):
Add the following to the top of your ApplicationController:
rescue_from Koala::Facebook::APIError, :with => :handle_fb_exception
Add the following protected method to your ApplicationController:
def handle_fb_exception exception
if exception.fb_error_type.eql? 'OAuthException'
logger.debug "[OAuthException] Either the user's access token has expired, they've logged out of Facebook, deauthorized the app, or changed their password"
oauth = Koala::Facebook::OAuth.new
# If there is a code in the url, attempt to request a new access token with it
if params.has_key? 'code'
code = params['code']
logger.debug "We have the following code in the url: #{code}"
logger.debug "Attempting to fetch a new access token..."
token_hash = oauth.get_access_token_info code
logger.debug "Obtained the following hash for the new access token:"
logger.debug token_hash.to_yaml
redirect_to root_path
else # Since there is no code in the url, redirect the user to the Facebook auth page for the app
oauth_url = oauth.url_for_oauth_code :permissions => 'email'
logger.debug "No code was present; redirecting to the following url to obtain one: #{oauth_url}"
redirect_to oauth_url
end
else
logger.debug "Since the error type is not an 'OAuthException', this is likely a bug in the Koala gem; reraising the exception..."
raise exception
end
end
The Koala calls were all taken from the following 2 tutorials:
https://github.com/arsduo/koala/wiki/OAuth
https://github.com/arsduo/koala/wiki/Koala-on-Rails
For those of you who don't have time to make this change, I found that you can disable this migration in Settings -> Advanced. The name of the option is "Remove offline_access permission:"

rails aws-s3 delete file throws AWS::S3::PermanentRedirect error - EU bucket problem?

I'm building a rails3 app on heroku, and I'm using aws-s3 gem to manipulate files stored in an Amazon S3 eu bucket.
When I try to perform a AWS::S3::S3Object.delete filename, 'mybucketname' command, I get the following error:
AWS::S3::PermanentRedirect (The bucket you are attempting to access
must be addressed using the specified endpoint. Please send all future
requests to this endpoint.):
I have added the following to my application.rb file:
AWS::S3::Base.establish_connection!(
:access_key_id => "myAccessKey",
:secret_access_key => "mySecretAccessKey"
)
and the following code to my controller:
def destroy
song = tape.songs.find(params[:id])
AWS::S3::S3Object.delete song.filename, 'mybucket'
song.destroy
respond_to do |format|
format.js { render :nothing => true }
end end
I found a proposed solution somewhere to add AWS_CALLING_FORMAT: SUBDOMAIN to my amazon_s3.yml file, as supposedly, aws-s3 should handle differently eu buckets than us.
However, this did not work, same error is received.
Could you please provide any assistance?
Thank you very much for your help.
the problem is you need to type SUBDOMAIN as uppercase string in config, try this out
You can specify custom endpoint at connection initialization point:
AWS::S3::Base.establish_connection!(
:access_key_id => 'myAccessKey',
:secret_access_key => 'mySecretAccessKey',
:server => 's3-website-us-west-1.amazonaws.com'
)
you can find actual endpoint through the AWS console:
full list of valid options - here https://github.com/marcel/aws-s3/blob/master/lib/aws/s3/connection.rb#L252
VALID_OPTIONS = [:access_key_id, :secret_access_key, :server, :port, :use_ssl, :persistent, :proxy].freeze
My solution is to set the constant to the actual service link at initialization time.
in config/initializers/aws_s3.rb
AWS::S3::DEFAULT_HOST = "s3-ap-northeast-1.amazonaws.com"
AWS::S3::Base.establish_connection!(
:access_key_id => 'access_key_id',
:secret_access_key => 'secret_access_key'
)

Tweeting using Twitter gem and Omniauth

I'm developing a web app that will let users tweet posts and links, but I can't seem to get Twitter and Omniauth to play nicely together. I'm currently running on Rails 3.0.6 and Ruby 1.8.7, with the Twitter gem 1.4.1 and Omniauth gem 0.2.5
I can authenticate the users fine, but when it comes to sending a tweet, I'm just given the error:
POST https://api.twitter.com/1/statuses/update.json: 401: Incorrect signature
I followed this tutorial, and have placed my consumer key and consumer secret in a Twitter configure block in my Omniauth initializer, but not the oauth token or oauth secret because these will surely be used on a per-user basis.
omniauth.rb
Twitter.configure do |config|
config.consumer_key = "XXXXXXXXXXXXXXXXXXXXXX"
config.consumer_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
end
user.rb
def twitter
unless #twitter_user
provider = self.authentications.find_by_provider('twitter')
#twitter_user = Twitter::Client.new(:oauth_token => provider.token, :oauth_token_secret => provider.secret) rescue nil
end
#twitter_user
end
I then form the request using:
current_user.twitter.update("Hello World!")
And that's what then gives me the 401 error.
Any ideas? Thanks!
Your user.rb code is using the wrong format. They've changed quite a lot. You need something like this now:
require 'twitter'
class TwitterToken < ConsumerToken
TWITTER_SETTINGS={:site=>"http://api.twitter.com", :request_endpoint => 'http://api.twitter.com',}
def self.consumer
#consumer||=OAuth::Consumer.new credentials[:key],credentials[:secret],TWITTER_SETTINGS
end
def client
Twitter.configure do |config|
config.consumer_key = TwitterToken.consumer.key
config.consumer_secret = TwitterToken.consumer.secret
config.oauth_token = token
config.oauth_token_secret = secret
end
#client ||= Twitter::Client.new
end
end
I was having similar problems with that version of OmniAuth, I moved back to version 0.2.0 and all the 401's stopped happening.