设计 omniauthable 使用“找不到路径的有效映射"来破坏 Omniauth 身份验证 [英] Devise omniauthable breaks Omniauth authentication with `Could not find a valid mapping for path`

查看:28
本文介绍了设计 omniauthable 使用“找不到路径的有效映射"来破坏 Omniauth 身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我有两种类型的用户:求职者和招聘经理.求职者没有模型,他们只能使用从第三方提供商处收到的数据申请工作,同时通过 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_callbacksroutes.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屋!

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