Sinatra Logging into Facebook OAuth 2.0 with gem oauth2

I can go to the main URL, which is successfully redirected to facebook. I grant permission and I am redirected back to the callback url. If this URL just returns something like β€œhello”, it works fine without errors. But the call token = client.auth_code.get_token(@data[:code], :redirect_uri => redirect_uri) causes an error.

+4
source share
1 answer

Well, finally it worked out. The error reported was just some weird error handling thing and had nothing to do with the real problem. The problem was that the oauth2 gem is common, and you need to make a few words to make it work with facebook. This is what you need to do that are different from readme (see Questions 70 and 75 on github for more information)

Before creating your client, you must register a parser to respond to facebook:

 OAuth2::Response.register_parser(:facebook, 'text/plain') do |body| token_key, token_value, expiration_key, expiration_value = body.split(/[=&]/) {token_key => token_value, expiration_key => expiration_value, :mode => :query, :param_name => 'access_token'} end 

You must also set the token URL for the client when creating:

  @client = OAuth2::Client.new(ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET'], {:site => 'https://graph.facebook.com', :token_url => '/oauth/access_token'}) 

When oauth receives the response, it uses a parser that you tell it to use to parse the response into a hash. Custom: the facebook parser ensures that the hash contains the access token and the string expires and tells it to use the request mode and that the parameter name is access_token. Without mode and param_name, the Oauth client will attempt to send an access token to the header, rather than a query string when accessing resources. Facebook expects the access token to be specified in the URL. Without param_name, the oauth client sends it as https://graph.facebook.com/bearer_token=ABC . With param_name this is https://graph.facebook.com/access_token=ABC

Finally, when you create your AccessToken object, be sure to tell it to use its own parser like this:

 token = client.auth_code.get_token(@data[:code], {:redirect_uri => redirect_uri, :parsed => :facebook}) 

In general, it looks like this:

 require 'sinatra' require 'oauth2' require 'json' class App < Sinatra::Base configure do set :views_folder, File.join($BP, 'views') set :public_folder, File.join($BP, 'public') end before do @data = JSON.parse(request.env["rack.input"].read) if request.request_method =~ /POST|PUT|DELETE/i @data = params if request.request_method == 'GET' end before do pass if (request.path_info == '/auth/facebook' || request.path_info == '/auth/facebook/callback') redirect to('/auth/facebook') unless self.logged_in end get "/" do request.request_method end def client if !@client OAuth2::Response.register_parser(:facebook, 'text/plain') do |body| token_key, token_value, expiration_key, expiration_value = body.split(/[=&]/) {token_key => token_value, expiration_key => expiration_value, :mode => :query, :param_name => 'access_token'} end @client = OAuth2::Client.new(ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET'], {:site => 'https://graph.facebook.com', :token_url => '/oauth/access_token'}) end @client end get '/auth/facebook' do redirect client.auth_code.authorize_url( :redirect_uri => redirect_uri, :scope => 'email' ) end get '/auth/facebook/callback' do token = client.auth_code.get_token(@data[:code], {:redirect_uri => redirect_uri, :parsed => :facebook}) user = token.get('/me').parsed create_user user unless user_exists user end def redirect_uri uri = URI.parse(request.url) uri.path = '/auth/facebook/callback' uri.query = nil uri.to_s end end 
+6
source

Source: https://habr.com/ru/post/1391008/


All Articles