Rails中Devise-Omniauth路由指向passthru而非Twitter的问题排查
Devise集成omniauth-twitter出现"Not found. Authentication passthru"错误排查
问题现象
尝试在Ruby on Rails中通过Devise集成omniauth-twitter,按照官方文档使用POST请求的授权链接:
<%= link_to "Sign up with twitter", user_twitter_omniauth_authorize_path, method: :post %>
已通过Turbo.session.drive = false全局禁用Turbo,但点击链接后页面显示:
Not found. Authentication passthru.
查看路由发现异常:
% bin/rails routes -g omni Prefix Verb URI Pattern Controller#Action user_twitter_omniauth_authorize GET|POST /users/auth/twitter(.:format) users/omniauth_callbacks#passthru user_twitter_omniauth_callback GET|POST /users/auth/twitter/callback(.:format) users/omniauth_callbacks#twitter
授权路由指向不存在的Users::OmniauthCallbacksController#passthru方法,且已通过日志确认使用POST请求,排除请求方法和Turbo影响。
已确认的前提条件
- 使用Twitter OA1 API密钥(OA2暂不被Omniauth支持)
- 已在Twitter开发者中心启用"User authentication set up",允许用户登录
相关配置文件
Gemfile
# Gemfile gem 'devise' gem 'devise-i18n' gem 'omniauth', '~> 2.1' gem 'omniauth-twitter' gem 'omniauth-rails_csrf_protection', '~> 1.0'
注:已将omniauth-rails_csrf_protection从0.1.2升级到1.0.1,问题仍存在
config/initializers/devise.rb
# /config/initializers/devise.rb Devise.setup do |config| config.omniauth :twitter, 'MY_APP', 'MY_SECRET' OmniAuth.config.logger = Rails.logger if Rails.env.development? # 调试用 end
注:config/initializers/目录下无其他Omniauth或Twitter相关配置文件
app/models/user.rb
# /models/user.rb class User < ApplicationRecord devise :database_authenticatable, :registerable, # 省略其他配置 :omniauthable, omniauth_providers: %i(twitter) def self.from_omniauth(auth) find_or_create_by(provider: auth.provider, uid: auth.uid) do |user| user.display_name = auth.info.nickname.strip user.skip_confirmation! end end end
app/controllers/users/omniauth_callbacks_controller.rb
# /app/controllers/users/omniauth_callbacks_controller.rb class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController skip_before_action :verify_authenticity_token, only: [:twitter] def twitter callback_from __method__ end def callback_from(provider) @user = User.from_omniauth(request.env['omniauth.auth']) if @user.persisted? sign_in_and_redirect @user, event: :authentication set_flash_message(:notice, :success, kind: provider.to_s.capitalize) if is_navigational_format? else session["devise.#{provider.to_s}_data"] = request.env['omniauth.auth'].except(:extra) redirect_to new_user_registration_url(from_omniauth_callback: true) end end def failure redirect_to root_path end end
config/routes.rb
# /config/routes.rb Rails.application.routes.draw do devise_for :users, except: [:destroy], controllers: { omniauth_callbacks: 'users/omniauth_callbacks' } end
视图文件
<%# /app/views/devise/registrations/new.html.erb %> <%= link_to t(".sign_up_with_twitter"), user_twitter_omniauth_authorize_path, method: :post, data: { turbo: false } %>
服务器日志
00:... | I, [2022-...6 #793] INFO -- : Started POST "/en/users/auth/twitter" for 127.0.0.1 at 2022-11-27 00:33:14 +0000 00:... | I, [2022-...4 #793] INFO -- : Processing by Users::OmniauthCallbacksController#passthru as HTML 00:... | I, [2022-...0 #793] INFO -- : Parameters: {"authenticity_token"=>"[FILTERED]", "locale"=>"en"} 00:... | D, [2022-...0 #793] DEBUG -- : Rendering text template 00:... | I, [2022-...7 #793] INFO -- : Rendered text template (Duration: 0.0ms | Allocations: 10) 00:... | I, [2022-...9 #793] INFO -- : Completed 404 Not Found in 4ms (Views: 2.5ms | ActiveRecord: 0.0ms | Allocations: 1170)
版本信息
omniauth-rails_csrf_protection(1.0.1)omniauth(2.1.0)omniauth-oauth(1.2.0)omniauth-twitter(1.4.0)devise(4.8.1)rails(7.0.4)ruby(3.1.2)
可能的原因及解决方法
1. Omniauth策略未正确加载
passthru是Devise在找不到对应Omniauth策略时的 fallback 动作,说明Rails未正确加载omniauth-twitter策略。
- 执行
bundle install后重启服务器,确保omniauth-twittergem已正确安装 - 确认
config/initializers/devise.rb中config.omniauth :twitter, 'MY_APP', 'MY_SECRET'的API密钥和密钥为真实有效内容 - 尝试在
config/application.rb中添加require 'omniauth-twitter',强制加载策略
2. Omniauth 2.x CSRF保护配置冲突
Omniauth 2.x对CSRF保护要求更严格,可能存在配置冲突:
- 移除控制器中的
skip_before_action :verify_authenticity_token, only: [:twitter],omniauth-rails_csrf_protection会自动处理回调的CSRF验证 - 确认视图中
link_to的method: :post正确生成POST请求,而非默认GET
3. Devise与Omniauth路由映射异常
路由指向passthru说明Devise未正确映射授权路径到Omniauth逻辑:
- 检查
User模型中devise ... :omniauthable, omniauth_providers: %i(twitter)配置完整,确保:omniauthable和omniauth_providers已添加 - 执行
rails generate devise:omniauth_callbacks User重新生成回调控制器,对比现有控制器的差异 - 确认
routes.rb中devise_for :users的控制器映射正确
4. Twitter开发者配置缺失
尽管已启用用户认证,仍可能存在配置遗漏:
- 在Twitter开发者中心,确认应用的"Callback URL"设置为开发环境的
http://localhost:3000/users/auth/twitter/callback(生产环境替换为真实域名) - 确认应用的"App permissions"至少设置为"Read"权限
- 再次核对API密钥和密钥,确保无多余空格或字符
内容的提问来源于stack exchange,提问作者Masa Sakano
相关产品推荐
相关产品推荐

