Devise / OmniAuth不签署某些用户

时间:2013-06-30 20:50:47

标签: ruby-on-rails devise twitter omniauth twitter-oauth

我们的产品是Rails应用程序;身份验证由Devise和OmniAuth处理。总共~2000个用户。我们最近有一些用户无法登录的报告,但我们无法弄清楚原因。没有任何服务器错误或我们的生产日志中的任何内容提出任何建议都是错误的。

让我们看看一些代码......

class OmniauthCallbacksController < Devise::OmniauthCallbacksController

  ...

  def twitter
    oauthorize "twitter"
  end

  private

  def oauthorize(provider)
    if env['omniauth.auth']
      @identity = Identity.from_omniauth(env['omniauth.auth'])
      @person = @identity.person
      # 1. failing here? Maybe?
      if @person
        PersonMeta.create_for_person(@person, session[:referrer], session[:landing_page]) if @person.first_visit?
        # 2. PersonMetas *aren't* being created.
        flash[:notice] = I18n.t("devise.omniauth_callbacks.success", kind: provider)
        sign_in_and_redirect(@person, :event => :authentication)
        # 3. Definitely failing by here…
      else
        redirect_to root_url
      end
    else
      redirect_to root_url
    end
  end
end

class Identity < ActiveRecord::Base
  belongs_to :person, counter_cache: true, touch: true
  after_create :check_person

  def self.from_omniauth(auth)
    where(auth.slice("provider", "uid")).first_or_initialize.tap do |identity|
      identity.oauth_token = auth['credentials']['token']
      identity.oauth_secret = auth['credentials']['secret']
      case auth['provider']
      when "twitter"
        identity.name = auth['info']['name']
        identity.nickname = auth['info']['nickname']
        identity.bio = auth['info']['description']
        identity.avatar_address = auth['info']['image']
      else
        raise "Provider #{provider} not handled"
      end
      identity.save
    end
  end

  def check_person
    if person_id.nil?
      p = create_person(nickname: nickname, name: name, remote_avatar_url: biggest_avatar)
      p.identities << self
    end
  end

  def biggest_avatar
    avatar_address.gsub('_bigger', '').gsub('_normal', '') if avatar_address
  end
end

class PersonMeta < ActiveRecord::Base
  attr_accessible :landing_page, :mixpanel_id, :referrer_url, :person_id
  belongs_to :person

  def self.create_for_person(person, referrer, landing_page)
    PersonMeta.create!(referrer_url: referrer, landing_page: landing_page, person_id: person.id)
  end
end

所以我们有这个,我们在生产中没有任何错误。

我们从哪里开始?好吧,让我们看看失败点是否是Identity.from_omniauth

此方法搜索现有标识(我们为更多提供程序编写了额外代码,但尚未在客户端实现)。如果未找到任何标识,则会创建一个标识,然后创建关联的Person模型。如果这是失败的原因,我们将能够在生产控制台中看到一些可疑的空字段。但不 - 人与人所有标识模型都使用所有正确的字段创建,并且应用程序的相关位已经看到它们(例如,它们的“用户配置文件页面”都已创建)。

我刚刚在if @person添加了#oauthorize - 我们有一个500 @identity.person nil,但无法复制。

无论如何,有问题的真实用户拥有完整的关联模型。向下移动该方法,我们创建一个PersonMeta记录来记录简单的内容,如登录页面。我已经在after_create上以Person完成了此操作,但我认为将会话数据传递给模型是不对的。

这不是为有问题的用户创建的。在这一点上,我有点难过。我不确定创建(带有爆炸声)是如何进入的,但如果某事被破坏,这不应该抛出异常吗?事实并非如此。

只有当这是一个人的第一次访问时才会被调用 - 后续登录应绕过它。其中一个有问题的用户是朋友,所以我一直让他尝试各种其他的东西,包括再次登录,尝试不同的浏览器等,并且一直在发生

所以无论如何,写完这篇文章花了45分钟......

其中一位用户通过Twitter撤销了对该应用的访问权限并重新进行了身份验证。现在一切都有效。

到底是什么?

他的旧身份 他的OAuth令牌等正确存储。

幸运的是,一个用户已经解决了这个问题,但这显然是一个持续存在的问题。

我们做什么?

1 个答案:

答案 0 :(得分:0)

identity.save中的Identity.from_omniauth行是否可能无声地失败?如果是这样,您的after_create挂钩将无法运行,@identity.person将为nil,您只会(默默地)重定向。

试试identity.save!