我们的产品是Rails应用程序;认证由Devise和OmniAuth处理。总共约2000个用户。我们最近收到了一些用户无法登录的报告,但我们无法弄清楚原因。没有得到任何服务器错误或我们的生产日志中的任何东西来表明任何错误。Devise/OmniAuth未登录某些用户
让我们看看一些代码...
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
记录来记录诸如登录页面之类的简单内容。我在Person
上以after_create
的身份完成了这项工作,但我认为将会话数据传递给模型是不对的。
这不是为我们有问题的用户创建的。在这一点上,我很难过。我不知道如何创建!(砰的一声)进去了,但是如果有什么东西坏了,不应该抛出异常吗?事实并非如此。
只有当它是一个人的第一次访问时才被调用 - 后续登录应该绕过它。一个有问题的用户是朋友,所以我一直让他尝试各种其他的东西,包括再次登录,尝试不同的浏览器等,它持续发生
所以,无论如何,花45分钟写入后这篇文章...
其中一个用户通过Twitter取消了对应用程序的访问并重新进行了认证。现在一切正常。
到底是什么?
他的老身份有他OAuth凭证等妥善保存。
幸运的是这解决了一个用户,但它显然一直存在的问题。
我们该怎么办?
我不这么认为 - 就像我说的,对于每个受影响的用户,他们都有有效和完整的身份和人员字段=/ –
您是否有任何具有'nil'的PersonMeta' person_id在数据库中? – nickgrim
不是 - 它们要么被正确创建,要么不存在。 –