设计 omniauthable 使用“找不到路径的有效映射"来破坏 Omniauth 身份验证 [英] Devise omniauthable breaks Omniauth authentication with `Could not find a valid mapping for path`
问题描述
在我的项目中,我有两种类型的用户:求职者和招聘经理.求职者没有模型,他们只能使用从第三方提供商处收到的数据申请工作,同时通过 Omniauth 进行身份验证.招聘经理的信息存储在设计用户模型中.招聘经理还必须能够使用其公司的 Google 电子邮件帐户登录.因此,首先我使用 Omniauth 1.0.0、Rails 3.1.3 构建了求职者的身份验证:
In my project, I have two type of users: job seekers and hiring managers. Job seekers don't have a model, they are just able to apply for jobs using the data received from from third-party providers while authenticating thru Omniauth. Hiring managers' info is stored in devise User model. Hiring managers also must be able to sign in with their company's Google email account. So, first I built job seekers' authentication using Omniauth 1.0.0, Rails 3.1.3:
omniauth.rb
require 'omniauth-openid'
require 'openid/store/filesystem'
Rails.application.config.middleware.use OmniAuth::Builder do
provider :openid, :store => OpenID::Store::Filesystem.new('./tmp'), :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id'
provider :facebook, "xxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
{:scope => 'email, offline_access, publish_stream', :client_options => {:ssl => {:ca_file => '/usr/lib/ssl/certs/ca-certificates.crt'}}}
provider :twitter, "xxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
provider :linkedin, "xxxxxxxxxxx", "xxxxxxxxxxxxxxxxxxx"
end
在routes.rb
中:
match '/auth/:provider/callback', :to => 'sessions#authenticate_jobseeker'
match '/auth/failure', :to => 'sessions#failure'
在sessions_controller.rb
def authenticate_jobseeker
session[:jobseeker] = request.env['omniauth.auth']
if valid_job_seeker?
redirect_to new_job_application_path(...)
else
redirect_to request.env['omniauth.origin'] || root_path, alert: "Authentication failure"
end
end
到目前为止一切正常.但是,当我开始为 User 模型实现 Google 登录并添加 :omniauthable 时,我的求职者身份验证失败了.我正在使用设计 1.5.2:
Up to this point everything worked fine. However, when I started implementing Google sign on for User model, and added :omniauthable to it, my job seeker authentication broke. I am using Devise 1.5.2:
user.rb
class User < ActiveRecord::Base
#...
devise :database_authenticatable, :registerable,
... :lockable, :omniauthable
#...
end
在 devise.rb
中:
config.omniauth :open_id, :store => OpenID::Store::Filesystem.new('./tmp'), :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id', :require => 'omniauth-openid'
在routes.rb
中:
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } do
get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru'
end
此时,用户的身份验证有效,但求职者的身份验证无效.搜索了一段时间后,通过添加 :path_prefix => 解决了问题./auth"
到 omniauth.rb
中的每个提供程序.现在唯一的问题是,当求职者不允许访问其数据时(即按不允许"并返回到应用程序),我会收到每个提供程序的 RuntimeError:
At this point, Users' authentication worked, but job seekers' did not. After searching for a while, the issue was fixed by adding :path_prefix => "/auth"
to every provider in omniauth.rb
.
The only problem now, is when job seeker does not allow access to its data (i.e. presses "Don't Allow" and comes back to the application), I get following RuntimeError for every provider:
Could not find a valid mapping for path "/auth/twitter/callback"
Parameters:
{"denied"=>"mKjVfMRwRAN12ZxQ9cxCoD4rYSLJIRLnEqgiI"}
轨迹顶部:
devise (1.5.2) lib/devise/mapping.rb:48:in `find_by_path!'
devise (1.5.2) lib/devise/omniauth.rb:17:in `block in <top (required)>'
omniauth (1.0.0) lib/omniauth/strategy.rb:418:in `call'
omniauth (1.0.0) lib/omniauth/strategy.rb:418:in `fail!'
omniauth-oauth (1.0.0) lib/omniauth/strategies/oauth.rb:63:in `rescue in callback_phase'
omniauth-oauth (1.0.0) lib/omniauth/strategies/oauth.rb:45:in `callback_phase'
omniauth (1.0.0) lib/omniauth/strategy.rb:200:in `callback_call'
omniauth (1.0.0) lib/omniauth/strategy.rb:166:in `call!'
omniauth (1.0.0) lib/omniauth/strategy.rb:148:in `call'
omniauth (1.0.0) lib/omniauth/strategy.rb:168:in `call!'
omniauth (1.0.0) lib/omniauth/strategy.rb:148:in `call'
omniauth (1.0.0) lib/omniauth/strategy.rb:168:in `call!'
omniauth (1.0.0) lib/omniauth/strategy.rb:148:in `call'
omniauth (1.0.0) lib/omniauth/builder.rb:30:in `call'
我已经尝试解决它一段时间了.任何帮助是极大的赞赏.如果我能提供更多信息,请告诉我.
I've been trying to solve it for a while now. Any help is greatly appreciated. Let me know, if I can provide additional info.
推荐答案
回答我自己的问题.因此,最终决定是采用纯 Omniauth 实现.我从 User
模型中删除了 :omniauthable
,从 devise.rb
中删除了 config.omniauth...
,删除了 :omniauth_callbacks
从 routes.rb
设计路由.所以,所有用户(无论什么角色)都会使用 ame 回调路由并点击 sessions_controller#authenticate_jobseeker
动作(应该考虑重命名动作?):
Answering my own question. So, final decision was to go with pure Omniauth implementation. I removed :omniauthable
from User
model, removed config.omniauth...
from devise.rb
, removed :omniauth_callbacks
devise routes from routes.rb
.
So, all users (no matter what role) would use ame callback routes and hit sessions_controller#authenticate_jobseeker
action (should consider renaming the action?):
def authenticate_jobseeker
auth_hash = request.env['omniauth.auth']
unless auth_hash.present?
redirect_to request.env['omniauth.origin'] || root_path, alert: "Sorry, we were not able to authenticate you" and return
end
@user = User.find_from_oauth(auth_hash)
if @user.present?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Google"
sign_in_and_redirect @user, :event => :authentication and return
else
session[:jobseeker] = auth_hash["info"]
if valid_job_seeker?
redirect_to new_job_application_path(...)
end
end
end
和User.find_from_oauth
:
def self.find_from_oauth(auth_hash)
if auth_hash
user = User.where(:email => auth_hash["info"]["email"]).first
end
user
end
此实现满足所有要求.
这篇关于设计 omniauthable 使用“找不到路径的有效映射"来破坏 Omniauth 身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!