Sinatra使用gem oauth2登录Facebook OAuth 2.0

我可以导航到成功重定向到facebook的主网址.我授予权限,我被重定向回回调网址.如果这个url只是返回类似’hello’的东西,那么它可以正常工作,没有错误.但是调用token = client.auth_code.get_token(@data [:code],:redirect_uri => redirect_uri)会导致错误.
好的,终于有了这个工作.报告的错误只是错误处理的一些奇怪的事情,与实际问题无关.问题是oauth2 gem是通用的,你必须要做一些事情才能使它与facebook一起工作.这些是您必须做的与自述文件不同的内容(有关详细信息,请参阅 github上的问题70和75)

在创建客户端之前,必须为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

您还必须在创建时为客户端设置令牌URL:

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

当oauth收到响应时,它会使用您告诉它使用的解析器将响应解析为哈希.自定义:facebook解析器确保哈希包含访问令牌和expires字符串并告诉它使用查询模式并且param名称是access_token.如果没有mode和param_name,Oauth客户端将在访问资源时尝试在标头而不是查询字符串中发送访问令牌. Facebook希望访问令牌在网址中.如果没有param_name,oauth客户端将其发送为
https://graph.facebook.com/bearer_token=ABC.使用param_name,它是https://graph.facebook.com/access_token=ABC

最后,当您创建AccessToken对象时,请务必告诉它使用您的自定义解析器,如下所示:

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

总之它看起来像:

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
相关文章
相关标签/搜索