我们有一个使用设计&设计的rails应用程序设置omniauth允许通过facebook身份验证登录。我们还有一个移动应用程序,目前正在使用http身份验证登录到rails应用程序,方法是通过用户名&密码或传入http身份验证令牌。到目前为止,这一切都很有效。
移动应用程序还可以通过Facebook本身进行身份验证,并直接在自己和Facebook之间接收用户facebook令牌。
我想弥合这个差距,以便如果用户通过Facebook从移动应用程序登录并拥有他们的facebook令牌,请允许将facebook令牌用作rails app上的身份验证,就像他们已经收到它一样从Facebook通过浏览器。
最终结果是移动应用可以通过以下方式登录用户:
1)用户名/密码 要么 2)http认证令牌 要么 3)omniauth(facebook)令牌
此外,在3)的情况下,如果用户尚未存在于rails应用程序中,则需要创建用户 - 现在已经使用浏览器端身份验证执行此操作,因此可能无需执行任何操作。< / p>
如何在设计构造中做到最好?
答案 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