如何使用设计中的http身份验证与可选的omniauth令牌作为身份验证令牌 [英] How to use http authentication in devise with an optional omniauth token as the authentication token

查看:112
本文介绍了如何使用设计中的http身份验证与可选的omniauth令牌作为身份验证令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个rails应用程序设置,使用devise& omn​​iauth允许通过Facebook身份验证登录。我们还有一个移动应用程序,目前正在使用http身份验证登录到rails应用程序,通过传递用户名和密码或通过传递http身份验证令牌。



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

我想填补这个差距,以便如果用户已经通过Facebook从移动应用程序登录并且拥有其facebook令牌,则可以将该facebook令牌用作 rails应用程序就像通过浏览器从Facebook接收到的那样。



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



1)用户名/密码

2)http身份验证令牌

3)omniauth(facebook)令牌



另外,在3)的情况下,如果用户在rails应用程序中还不存在,则需要创建用户 - 现在已经使用浏览器端验证,因此可能不要再做了。



如何在设计结构中最好地完成这项工作?

解决方案

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



2可以很容易地在设计和其他地方记录下来。



不要太多的添加FB auth到你的网络应用程序,这些说明在github上为omniauth和omniauth-facebook。 / p>

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



您需要fb_graph gem。



在移动客户端上,您可以使用FB进行身份验证,并将其放在您的http请求的标题中返回的访问令牌。我使用标题fb_access_token。 就像基本认证一样,您需要通过SSL发送,以避免嗅探令牌。使用标题可以让我在不改变请求的情况下交换基本的验证码和FB验证码,但是您可以使用参数,如果您愿意的话。



此解决方案实施了一个基于设计认证守护者策略的监督策略。这里的不同之处在于,该策略利用了一个名为fb_access_token的HTTP头,其中包含使用移动应用程序检索的facebook访问令牌字符串。



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



在一个文件中,在config / initializers目录中添加以下内容。我碰巧打电话给我的fb_api_strategy.rb:

 #身份验证策略,通过webservice支持API认证
#通过Facebook

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

module Devise
module Strategies
class FbMobileDatabaseAuthenticatable<验证
def有效?
#如果我们拥有Facebook访问键的标题
!! 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)

#这将为有效的FB帐户创建一个新用户,或将
#此会话附加到与FB帐户具有相同电子邮件的现有用户

如果!!用户&&&验证(用户){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应用程序的访问令牌将会有所不同。这可能会影响您的缓存方案。



我认为这样做 - 快乐的编码。


We have a rails app setup that uses devise & omniauth to allow logging in via facebook authentication. We also have a mobile app that is currently using http authentication to login to the rails app either by passing username & password or by passing in the http authentication token. This all works great so far.

The mobile app also has the ability to authenticate with facebook itself and receive the user facebook token directly between itself and facebook.

I would like to bridge this gap so that if the user has logged in from the mobile app via facebook and has their facebook token, allow that facebook token to be used as the authentication on the rails app as if they had received it from facebook via the browser.

The end result would be that the mobile app can log a user in via:

1) username/password or 2) http authentication token or 3) omniauth (facebook) token

Also, in the case of 3), if the user doesn't yet exist on the rails app, would need to create the user - doing that now already with browser side authentication so there may be nothing more to do.

How can I best accomplish this within the devise construct?

解决方案

Just did this, but never saw an end-to-end solution.

This addresses point 3. 1 & 2 are easily accomplished with devise and documented elsewhere.

Not too hard to add FB auth to your web app, the instructions are on github for omniauth and omniauth-facebook.

I believe the following stands alone, without doing the omniauth-facebook integration, if you want to do it that way. This is similar to other approaches out there. My idea was to attempt to use the devise model as closely as I could.

You'll need the fb_graph gem.

On the mobile client, you authenticate with FB appropriately and put the returned access token in the header of your http requests. I used the header fb_access_token. Just like basic auth, you'll want to send this over SSL to avoid sniffing of the token. Using the header allows me to interchange basic auth and FB auth without changing the requests, but you could use a parameter if you prefer.

This solution implements a warden strategy which is based off of the devise Authenticatable warden strategy. The difference here is the fact that this strategy utilizes an HTTP header called fb_access_token containing the facebook access token string that was retrieved using the mobile application.

Once you know this, the code is pretty straightforward.

In a file, in the config/initializers directory, add the following. I happened to call mine 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)

In config/initializers, add the following to devise.rb:

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

To allow you to either create a user or find an existing user based on the FB email, add the following to your user model:

  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

I don't think fb_database_authenticatable is an accurate name, but I'll leave that as an exercise for the reader. Another exercise is caching/storing the FB access token, and perhaps avoiding the RT to FB with each call. You should note that the access token from the the mobile app and the rails app will be different if you do FB authentication on both sides, which I suspect most people will want to do. This probably impacts your caching scheme.

I think that does it - happy coding.

这篇关于如何使用设计中的http身份验证与可选的omniauth令牌作为身份验证令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆