Ruby on rails Oauth2流使用Facebook uid请求令牌作为凭据

Ruby on rails Oauth2流使用Facebook uid请求令牌作为凭据,ruby-on-rails,authentication,oauth-2.0,Ruby On Rails,Authentication,Oauth 2.0,我正在构建一个带有Rails后端的iPhone客户端。客户机通过OAuth2API与服务器通信。我已经使用oauth2和门卫宝石设置了这个 每个API请求都必须与令牌一起发送。我目前支持两种令牌“类型”: 客户端:使用客户端凭据授予类型。这适用于非用户特定请求,如访问应用程序范围的资产、密钥等 用户:使用密码凭据授予类型。要获取此令牌,客户端必须通过传递有效的用户名/密码组合来请求它。所有用户请求都使用此令牌 这一切都很好,但我现在遇到了一个问题,因为我允许用户也使用Facebook登录应用

我正在构建一个带有Rails后端的iPhone客户端。客户机通过OAuth2API与服务器通信。我已经使用oauth2和门卫宝石设置了这个

每个API请求都必须与令牌一起发送。我目前支持两种令牌“类型”:

  • 客户端:使用客户端凭据授予类型。这适用于非用户特定请求,如访问应用程序范围的资产、密钥等
  • 用户:使用密码凭据授予类型。要获取此令牌,客户端必须通过传递有效的用户名/密码组合来请求它。所有用户请求都使用此令牌
这一切都很好,但我现在遇到了一个问题,因为我允许用户也使用Facebook登录应用程序

用户登录FB后,我的客户端通过将Facebook UID传递给我的服务器(使用客户端令牌)进行响应。然后,我在服务器上进行一些检查,以将此UID与数据库中的现有用户相匹配

问题是:我想用一个用户令牌响应这个请求。此令牌是必需的,因为用户现在将登录到应用程序,任何后续请求都将需要此令牌。然而,目前我觉得我唯一能做到这一点的方法是:

回复用户名和密码。然后让客户端按照密码凭据流请求用户令牌。我不喜欢这样,因为我要传递密码,而且需要多次访问


我觉得我可能错过了一些基本的东西。是否有其他方法可以处理此流程?

我想我有一个解决方案,但它肯定是一个黑客

基本上,我劫持了密码凭证流来处理这个Facebook场景

客户机这样调用(我在ruby中测试时,格式化可能已关闭):

在我的服务器上,我检查“provider”参数。如果找到,它将使用facebook uid在用户表中查找匹配项,而不是密码身份验证。我还将传递FB令牌作为安全措施(在查找匹配项之前,我验证此令牌是否属于uid)。如果找到匹配项,则将用户设置为令牌的资源所有者,这意味着我最终会得到一个用户令牌

这是my doorkeeper.rb中的代码块:

resource_owner_from_credentials do |routes|
 if params[:provider]
    // FB uid authentication path code here
 else
   // password authentication
   user = User.find_by_email(params[:username])
   user if user && user.authenticate(params[:password])
 end
end
resource_owner_authenticator do   
  user_from_session || begin
    session[:return_to] = request.fullpath

    fb_login_url = "..." # add here your facebook login url 
    redirect_to(fb_login_url)
  end
end

OAuth 2.0定义的资源所有者密码凭据类型实际上不适合外部登录,例如Facebook,因为身份验证是通过外部站点完成的,而不是通过您自己的授权服务器上的用户名和密码

一种解决方案是切换到OAuth 2.0()的隐式授权类型。门卫也支持这种类型

从应用程序中,您必须打开一个web视图,并使用以下参数将用户重定向到Doorkeeper的授权端点(默认值:/oauth/authorize):client_id=…,redirect_uri=。。。响应类型=令牌。此外,您必须告诉门卫将用户重定向到FB登录

因此,将其添加到doorkeeper.rb:

resource_owner_from_credentials do |routes|
 if params[:provider]
    // FB uid authentication path code here
 else
   // password authentication
   user = User.find_by_email(params[:username])
   user if user && user.authenticate(params[:password])
 end
end
resource_owner_authenticator do   
  user_from_session || begin
    session[:return_to] = request.fullpath

    fb_login_url = "..." # add here your facebook login url 
    redirect_to(fb_login_url)
  end
end

在用户通过FB登录并在服务器上对用户进行身份验证后,您必须将用户重定向回会话[:return_to]指向/oauth/authorize的内容,并重定向到最初给定的重定向uri,包括url中的访问令牌。

您是最终改进了这种方法,还是坚持使用这种方法?我正与这个挑战作斗争。