如何在设计中使用http身份验证,并使用可选的omniauth令牌作为身份验证令牌

时间:2011-08-29 15:50:28

标签: ruby-on-rails facebook devise omniauth http-authentication

我们有一个使用设计&设计的rails应用程序设置omn​​iauth允许通过facebook身份验证登录。我们还有一个移动应用程序,目前正在使用http身份验证登录到rails应用程序,方法是通过用户名&密码或传入http身份验证令牌。到目前为止,这一切都很有效。

移动应用程序还可以通过Facebook本身进行身份验证,并直接在自己和Facebook之间接收用户facebook令牌。

我想弥合这个差距,以便如果用户通过Facebook从移动应用程序登录并拥有他们的facebook令牌,请允许将facebook令牌用作rails app上的身份验证,就像他们已经收到它一样从Facebook通过浏览器。

最终结果是移动应用可以通过以下方式登录用户:

1)用户名/密码 要么 2)http认证令牌 要么 3)omniauth(facebook)令牌

此外,在3)的情况下,如果用户尚未存在于rails应用程序中,则需要创建用户 - 现在已经使用浏览器端身份验证执行此操作,因此可能无需执行任何操作。< / p>

如何在设计构造中做到最好?

2 个答案:

答案 0 :(得分:10)

刚刚做到这一点,但从未见过端到端的解决方案。

这解决了第3点和第1点的问题。 2可以通过设计和其他地方的文档轻松完成。

将FB身份验证添加到您的网络应用程序并不太难,指示在omithuth和omniauth-facebook的github上。

如果你想这样做,我相信以下是独立的,没有进行omniauth-facebook整合。这类似于其他方法。我的想法是尝试尽可能地使用设计模型。

你需要fb_graph gem。

在移动客户端上,您可以适当地使用FB进行身份验证,并将返回的访问令牌放入http请求的标头中。我使用了标头fb_access_token。 就像基本身份验证一样,你需要通过SSL发送它以避免嗅探令牌。使用头允许我交换基本身份验证和FB身份验证而不更改请求,但你可以使用参数如果你愿意。

此解决方案实现了一个基于可验证的可验证监管策略的监管策略。这里的区别在于,此策略使用名为fb_access_token的HTTP标头,其中包含使用移动应用程序检索的facebook访问标记字符串。

一旦你知道这一点,代码非常简单。

在文件的config / initializers目录中,添加以下内容。我碰巧叫我的fb_api_strategy.rb:

# authentication strategy to support API authentication over the webservice
# via facebook

require 'devise/strategies/database_authenticatable'
require 'fb_graph'
require 'warden'

module Devise
  module Strategies
    class FbMobileDatabaseAuthenticatable < Authenticatable
  def valid?
    # if we have headers with the facebook access key
    !!request.headers["fb_access_token"]
  end

  def authenticate!
    token = request.headers["fb_access_token"]
    fbuser = FbGraph::User.me(token)
    fbuser = fbuser.fetch

    user = User.find_for_facebook_mobile_client(fbuser.email)

    # this either creates a new user for the valid FB account, or attaches
    # this session to an existing user that has the same email as the FB account

    if !!user && validate(user) { true }
      user.after_database_authentication
      success!(user)
    elsif !halted? || !user
      fail(:invalid)
        end
      end
    end
  end
end

Warden::Strategies.add(:fb_database_authenticatable,
                       Devise::Strategies::FbMobileDatabaseAuthenticatable)

在config / initializers中,将以下内容添加到devise.rb:

  config.warden do |manager|
    manager.default_strategies(:scope => :user).unshift :fb_database_authenticatable
  end

要允许您根据FB电子邮件创建用户或查找现有用户,请将以下内容添加到您的用户模型中:

  def self.find_for_facebook_mobile_client(fb_email)
    if user = User.where(:email => fb_email).first
      user
    else
      User.create!(:email => fb_email, :password => Devise.friendly_token[0,20])
    end
  end

我认为fb_database_authenticatable不是一个准确的名字,但我会将其作为读者的练习。另一个练习是缓存/存储FB访问令牌,并且可能在每次调用时避免RT到FB。您应该注意,如果您在双方都进行FB身份验证,那么来自移动应用程序和rails应用程序的访问令牌会有所不同,我怀疑大多数人都希望这样做。这可能会影响您的缓存方案。

我认为这样做 - 编码很快。

答案 1 :(得分:0)

如果您在xcode 4.3.2中设置请求标头 你可以使用:

[request setValue:@"12345" forHTTPHeaderField:@"fbaccesstoken"];

但你不能使用:

[request setValue:@"12345" forHTTPHeaderField:@"fb_access_token"]; // does NOT get set