首页
学习
活动
专区
圈层
工具
发布

和OmniAuth
EN

Stack Overflow用户
提问于 2012-04-25 16:57:09
回答 1查看 2.4K关注 0票数 1

我已经成功地将OmniAuth Facebook登录流集成到服务器端的rails应用程序中。然而,我也试图让它在客户端使用来工作,并且遇到了一些问题。

编辑:这个问题似乎只发生在CHROME中,而不是在SAFARI或FIREFOX中。

会话控制器-在服务器端流上工作

代码语言:javascript
复制
def create

      auth = request.env['omniauth.auth']
      #if an authorization does not exisit, it will create a new authorization record. it will also create a new user record if a user is not currently logged in
      unless @auth = Authorization.find_from_hash(auth)
        # Create a new user or add an auth to existing user, depending on
        # whether there is already a user signed in.
        @auth = Authorization.create_from_hash(auth, current_user)

        #add the friends array to user record. as of now only doing this on the initial user create
        @friends = []
        FbGraph::User.me(@auth.user.authorization.facebook_token).fetch.friends.each do |t|
          @friends << t.identifier
        end
        u = @auth.user
        u.facebook_friends = @friends
        u.save

      end

      #store a new auth token if needed (if the new token in the hash does not match the one stored in the database for authorization)
      Authorization.check_if_new_auth_token_is_needed(auth)

      # Log the authorizing user in.
      self.current_user = @auth.user

      redirect_to root_url

  end

如果我只点击/auth/facebook路径,用户将被登录

路线

代码语言:javascript
复制
match '/auth/:provider/callback', :to => 'sessions#create'

现在,在主页视图中,我正在尝试运行客户端流登录。

主页查看

代码语言:javascript
复制
<script>
$(function() {
  $('a').click(function(e) {
    e.preventDefault();
    FB.login(function(response) {
      if (response.authResponse) {
        $('#connect').html('Connected! Hitting OmniAuth callback (GET /auth/facebook/callback)...');
        // since we have cookies enabled, this request will allow omniauth to parse
        // out the auth code from the signed request in the fbsr_XXX cookie
        $.getJSON('/auth/facebook/callback', function(json) {
          $('#connect').html('Connected! Callback complete.');
          $('#results').html(JSON.stringify(json));
        });
      }
    }, { scope: 'email,publish_stream' }); 
  });
});
</script>
<p id="connect">
          <a href="#">Connect to FB</a>
        </p>

        <p id="results" />

我的日志中有以下错误

{“错误”:{“消息”:“缺少授权代码”,“类型”:“OAuthException”,“代码”:1}

基本上,Omniauth并没有收到来自FB.login行动的facebook签名请求(正如https://github.com/mkdynamic/omniauth-facebook/blob/master/example/config.ru所说的那样)。

关于我如何使它正常工作或者我可能做错了什么?

EN

回答 1

Stack Overflow用户

发布于 2014-02-27 22:41:59

我意识到这个问题已经存在了一年,但我已经遇到了两次这个问题,所以希望这能帮助到一些人。

有两个与此问题相关的github线程:https://github.com/mkdynamic/omniauth-facebook/issues/73https://github.com/intridea/omniauth-oauth2/issues/31

问题的根源在于万能OAuth2GEM中的callback_phase方法:

代码语言:javascript
复制
if !options.provider_ignores_state && (request.params['state'].to_s.empty? || request.params['state'] != session.delete('omniauth.state'))
   raise CallbackError.new(nil, :csrf_detected)
end

Request.params‘’state‘和会话’Omauth.state‘都为零,因此条件失败,引发CallbackError异常。

一种解决方案是将provider_ignores_state设置为true,这绕过了条件:

代码语言:javascript
复制
config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET'], {
  strategy_class: OmniAuth::Strategies::Facebook,
  provider_ignores_state: true,
}

正如在上面的线程中所指出的,它不是一个永久的解决方案,因为它可以让您对csrf攻击保持开放。

另一件需要注意的事情是,Chrome在为本地主机编写cookie时遇到了问题。尝试使用lvh.me作为您的域(它解析为127.0.0.1)。

修补问题的更多代码通常不是一条很好的途径,但如果这两种解决方案都不起作用,那么您总是可以创建自己的处理程序并解析Facebook cookie:

代码语言:javascript
复制
def handle_facebook_connect
    @provider = 'facebook'
    @oauth = Koala::Facebook::OAuth.new(ENV["FACEBOOK_ID"], ENV["FACEBOOK_SECRET"])
    auth = @oauth.get_user_info_from_cookies(cookies)

    # Get an extended access token
    new_auth = @oauth.exchange_access_token_info(auth['access_token'])
    auth['access_token'] = new_auth["access_token"]

    # Use the auth object to setup or recover your user. The following is
    # and example of how you might handle the response
    if authentication = Authentication.where(:uid => auth['user_id'], :provider => @provider).first
      user = authentication.user
      sign_in(user, :event => :authentication)
    end

    # Redirect or respond with json 
    respond_to do |format|
      format.html { redirect_to user }
      format.json { render json: user } 
    end
end

然后,当收到连接的响应时,需要重定向到“handle_facebook_connect”方法:

代码语言:javascript
复制
FB.Event.subscribe('auth.authResponseChange', function(response) {
  if(response.status === 'connected'){
    if(response.authResponse){

      // Redirect to our new handler
      window.location = '/handle_facebook_connect';

      // Or make an ajax request as in the code in the original question:
      // $.getJSON('/handle_facebook_connect', function(json) {
      //   $('#connect').html('Connected! Callback complete.');
      //   $('#results').html(JSON.stringify(json));
      // });

    }
  } else if (response.status === 'not_authorized'){
    Facebook.message(Facebook.authorize_message);
  } else {
    FB.login();
  }
 });
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10320320

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档