如何使用可选omniauth令牌作为身份验证令牌使用http身份验证
我们有一个使用devise & omniauth允许通过Facebook身份验证登录的rails应用程序设置。我们还有一个移动应用程序,它目前使用http身份验证登录到Rails应用程序,方法是通过传递用户名&密码或传入http身份验证令牌。迄今为止,这一切都很有效。如何使用可选omniauth令牌作为身份验证令牌使用http身份验证
该移动应用程序还具有使用Facebook本身进行身份验证以及在其本身和Facebook之间直接接收用户Facebook令牌的能力。
我想填补这个空白,以便如果用户通过Facebook从移动应用程序登录并拥有他们的Facebook令牌,则允许将这个Facebook令牌用作Rails应用程序的身份验证,就好像他们已收到它从Facebook通过浏览器。
最终的结果将是,移动应用可以登录用户经由:
1)用户名/密码 或 2)HTTP认证令牌 或 3)omniauth(Facebook)的令牌
另外,在3)的情况下,如果用户还没有存在于Rails应用程序中,则需要创建用户 - 现在已经使用浏览器侧认证,因此可能没有什么可做的了。
我该如何在设计构造中最好地完成这件事?
刚刚做到了这一点,但从未见过端到端的解决方案。
此地址点3. 1 & 2很容易实现设计和记录在别处。
不难将FB认证添加到您的网络应用程序中,说明在github上为omniauth和omniauth-facebook。
我相信如果你想这样做,以下是独立的,没有做omniauth-facebook集成。这与其他方法类似。我的想法是试图尽可能使用设计模型。
您将需要fb_graph宝石。
在移动客户端上,您可以使用FB进行相应的身份验证,并将返回的访问令牌放入您的http请求的头部。我使用头fb_access_token。 就像基本身份验证一样,您需要通过SSL发送该消息以避免嗅探令牌。使用头允许我在不更改请求的情况下交换基本身份验证和FB身份验证,但是如果您愿意,可以使用参数。
该解决方案实现了基于设计Authenticatable监管策略的*战略。这里的区别在于这个策略使用了一个名为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)
在配置/初始化,添加以下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应用程序的访问令牌会有所不同。这可能会影响您的缓存方案。
我认为,做它 - 快乐编码。
如果您在Xcode 4.3.2 设置请求头,你可以使用:
[request setValue:@"12345" forHTTPHeaderField:@"fbaccesstoken"];
,但你不能使用:
[request setValue:@"12345" forHTTPHeaderField:@"fb_access_token"]; // does NOT get set
一些需要注意的:基本权限使用FB帐户不要提供电子邮件地址。你需要明确地询问用户这个权限。 – beeudoublez
好一点@beeudoublez,这正是我在我的应用程序一样。 – Matt