2012-01-14 68 views
4

我可以导航到成功重定向到Facebook的主要url。我授予权限,并且我被重定向回到了回调网址。如果这个url只是简单地返回类似'hello'的东西,那么它工作正常并没有错误。但拨打token = client.auth_code.get_token(@data[:code], :redirect_uri => redirect_uri)会导致错误。Sinatra使用gem oauth2登录到Facebook OAuth 2.0

回答

6

好吧终于得到了这个工作。被报告的错误是错误处理的一些奇怪的事情,并且与实际问题无关。问题是,oauth2宝石是通用的,你必须花费一些东西才能使它与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 

您还可以设置客户端的令牌网址上创造:

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

当OAuth的接收的响应,它使用你告诉它使用解析响应到一个哈希解析器。自定义:Facebook解析器确保哈希包含访问令牌和过期字符串,并告诉它使用查询模式,并且参数名称为access_token。如果没有模式和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 [email protected] 
     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 
+0

如果任何人看到最佳做法违规,请让我知道即时通讯设法得到更好的 – chris 2012-01-14 23:45:16

+0

我会考虑在路线之前分组你的帮手方法,但除此之外,这对我来说看起来不错。我正要着手学习如何自己做这个,所以谢谢你让我困惑不已:-) – 2012-01-16 22:13:10