简体   繁体   English

Rails Devise-omniauth 路由指向 passthru 而不是 twitter

[英]Rails Devise-omniauth route points to passthru instead of twitter

I am trying to implement omniauth-twitter with Devise in Ruby-on-Rails with no success.我正在尝试在 Ruby-on-Rails 中使用 Devise 实施omniauth-twitter但没有成功。 According to the definitive article of Devise , the link根据Devise 的权威文章,链接

<%= link_to "Sign up with twitter", user_twitter_omniauth_authorize_path,
    method: :post %>

should take the visitor to Twitter (Note I have disabled turbo site-wide with Turbo.session.drive = false and so turbo is irrelevant).应将访问者带到 Twitter(请注意,我已使用Turbo.session.drive = false在整个站点范围内禁用了turbo ,因此与turbo无关)。

However, it just displays但是,它只是显示

Not found.未找到。 Authentication passthru.身份验证直通。

I notice the route looks wrong in the first place:我注意到路线首先看起来是错误的:

% 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

It apparently points to Users::OmniauthCallbacksController#passthru , which is a non-existent method, hence the error?它显然指向Users::OmniauthCallbacksController#passthru ,这是一个不存在的方法,因此错误?

This problem has been reported multiple times in Stackoverflow and Github (eg, Github , SO1 , SO2 ).这个问题已经在 Stackoverflow 和 Github(例如GithubSO1SO2 )中多次报告。 A general advice seems to be using POST as opposed to GET.一般建议似乎是使用 POST 而不是 GET。 However, besides it is definitely POST in my case (as confirmed with a log file), I doubt if it is relevant to the routes!但是,除了在我的情况下它肯定是 POST(通过日志文件确认)之外,我怀疑它是否与路由相关!

What is the probable cause of this probblem and how can I solve it?这个问题的可能原因是什么,我该如何解决?

I confirm I am using OA1 API keys as opposed to Twitter OA2 (the latter is not supported by Omniauth, yet).. Also, as the doc of omniauth-twitter suggests, I confirm that "User authentication set up" is active in the Twitter Dev center to allow users to log in.我确认我使用的是 OA1 API 密钥而不是 Twitter OA2(Omniauth 尚不支持后者)。此外,正如omniauth-twitter 的文档所建议的,我确认“用户身份验证设置”在Twitter 开发中心允许用户登录。

My relevant files are as follows:我的相关文件如下:

 # Gemfile
gem 'devise'
gem 'devise-i18n'
gem 'omniauth', '~> 2.1' #, '1.9.1'
gem 'omniauth-twitter'
gem 'omniauth-rails_csrf_protection'
 # /config/initializers/devise.rb
Devise.setup do |config|
  config.omniauth :twitter, 'MY_APP', 'MY_SECRET'
  OmniAuth.config.logger = Rails.logger if Rails.env.development? # for debug
end

Note there are no Omniauth or Twitter-related configs in config/initializers/ .请注意,在config/initializers/中没有 Omniauth 或 Twitter 相关的配置。 Just devise.rb .只是devise.rb

 # /models/user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable, #...snipped...
         :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
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  skip_before_action :verify_authenticity_token, only: [:twitter]

  def twitter
    callback_from __method__
  end

  def callback_from(provider)
    # See User model
    @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
Rails.application.routes.draw do
  devise_for :users, except: [:destroy], 
    controllers: { omniauth_callbacks: 'users/omniauth_callbacks' } 
end

View (the turbo-part is meaningless, for it is globally turned off).查看(turbo-part 没有意义,因为它是全局关闭的)。

 <%# /app/views/devise/registrations/new.html.erb >
<%= link_to t(".sign_up_with_twitter"), user_twitter_omniauth_authorize_path,
  method: :post, data: { turbo: false } %>

The standard output of the server ( bin/dev in Rail 7):服务器的标准 output(Rail 7 中的bin/dev ):

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)

Version information版本信息

  • omniauth-rails_csrf_protection (0.1.2) → (1.0.1) omniauth-rails_csrf_protection (0.1.2) → (1.0.1)
    • Gemfile did not specify the version and yet a lower-version was installed. Gemfile没有指定版本,但安装了较低版本。 I now bundle install with '~> 1.0' .我现在将安装与'~> 1.0' bundle install在一起。 The same error still remains (after server-restart).同样的错误仍然存在(在服务器重启后)。
  • omniauth (2.1.0) omniauth (2.1.0)
  • omniauth-oauth (1.2.0) omniauth-oauth (1.2.0)
  • omniauth-twitter (1.4.0) omniauth-twitter (1.4.0)
  • devise (4.8.1) devise (4.8.1)
  • rails (7.0.4) rails (7.0.4)
  • ruby (3.1.2) ruby (3.1.2)

That's it.而已。 Thank you.谢谢你。

This isn't a full answer, but more of a suggestion of where to keep looking.这不是一个完整的答案,而是更多关于在哪里继续寻找的建议。

You are supposed to see (twitter) Request phase initiated.您应该会看到(twitter) Request phase initiated. in the logs immediately following Started POST "/users/auth/twitter" (from here ).Started POST "/users/auth/twitter" (来自此处)之后的日志中。

But, the Omniauth controller is instead looking for an HTML template to render (and failing to find one).但是,Omniauth controller 正在寻找一个 HTML 模板来渲染(但没有找到)。

INFO -- : Started POST "/en/users/auth/twitter" for 127.0.0.1 at 2022-11-27 00:33:14 +0000
INFO -- : Processing by Users::OmniauthCallbacksController#passthru as HTML
INFO -- :   Parameters: {"authenticity_token"=>"[FILTERED]", "locale"=>"en"}
DEBUG -- :   Rendering text template #<--- HERE!!!!
INFO -- :   Rendered text template (Duration: 0.0ms | Allocations: 10)
INFO -- : Completed 404 Not Found in 4ms (Views: 2.5ms | ActiveRecord: 0.0ms | Allocations: 1170)

This does make sense;这确实有道理; because Users::OmniauthCallbacksController#passthru is getting the POST request as HTML, it's looking for an HTML template to render (and failing to find one).因为Users::OmniauthCallbacksController#passthru正在获取 HTML 的 POST 请求,它正在寻找 HTML 模板来呈现(但找不到)。

It seems like Omniauth expects an AJAX request as JSON, not an HTML request.似乎 Omniauth 期望 AJAX 请求为 JSON,而不是 HTML 请求。

A few thoughts:一些想法:

  • Turn Turbo back on and see what the content-type of the request is when Turbo gets to decide重新打开 Turbo 并在 Turbo 决定时查看请求的content-type

  • Ditch the user_twitter_omniauth_authorize_path in favor of intercepting the link click and forming an AJAX POST request using Stimulus (Rails 7) or Javascript directly to the path /users/auth/twitter . user_twitter_omniauth_authorize_path以拦截链接点击并使用 Stimulus (Rails 7) 或 Javascript 直接向路径/users/auth/twitter形成 AJAX POST 请求。

  • The language "en" in the URL of the POST is probably coming from some other gem ( devise-i18n ?) That could be interfering with the POST request somehow and turning the content-type to HTML instead of JSON. POST 的 URL 中的语言“en”可能来自其他一些 gem(devise devise-i18n ?)这可能会以某种方式干扰 POST 请求并将内容类型转换为 HTML 而不是 JSON。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM