CSRF 检测修复 provider_ignores_state:在成功设计 Omniauth-Facebook 身份验证后真正不保存会话

CSRF Detection fix provider_ignores_state: true not saving session after successful Devise Omniauth-Facebook Authentication

我的应用程序工作正常,然后我更新到 Rails 5.0.1。此后,我的应用程序不再通过 Facebook 进行身份验证,并在日志中出现以下错误:

Authentication failure! csrf_detected: 
OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected

因此,根据 Whosebug 上的建议,我更改了我的 omniauth 配置以包含 provider_ignores_state: true 设置,从而抑制了该错误。

config.omniauth :facebook, 'xxx', 'xxxxxxxxxxxxx',{
      scope: 'public_profile,email,user_birthday,etc...',
      info_fields: 'name,first_name,etc...',
      provider_ignores_state: true
  }

这使一切正常;至少在本地开发 运行ning 中,但是当我将代码推送到我的登台服务器时,该应用程序成功通过 Facebook 进行身份验证,据推测 "signs" 用户进入并重定向到 root_path() - 然后身份验证失败并重定向回 users/sign_in.

为了帮助诊断问题,我在相关调用上方放置了一个日志行(以查看它是否正在执行),例如:

logger.debug "  (OmniauthCallbacksController#facebook) about to sign_in_and_redirect with id: #{@user.id} email: #{@user.email} uid: #{@user.provider_uid}"
sign_in_and_redirect @user, event: :authentication

我的 Facebook 提供商的 OmniauthCallbacksController 处理程序似乎确实达到了 'sign_in_and_redirect' - 但由于我无法确定我的暂存环境的原因,它实际上从未将会话保存到 cookie。日志中没有错误(在调试模式下)证明有任何类型的异常被抛出 - 除了增加用户 log_in_count 的查询实际上没有 运行 任何查询:

(2.4ms)  COMMIT
(0.2ms)  BEGIN
(0.2ms)  COMMIT

这看起来很奇怪(没有实际的更新查询,而在开发中我可以看到 log_in_count 等被递增)。但这是出现问题的唯一其他迹象。之后,它无法通过 authenticate_user! 检查并重定向回 sign_in_url.

这让我很生气 - 这是一个错误,还是有针对此问题的修复程序?

我终于解决了这个问题,但我还是不明白哪里出了问题。基本上,创建了一个 "empty" Rails 5 项目并使用 omniauth-facebook gem 和我的主要应用程序的设置设置了一个全新的设计 - 部署到登台服务器的克隆实例,它成功了!大部分代码是相同的;但是当我用新应用程序中的初始化程序替换 devise.rb 初始化程序时,旧代码再次在 stagingg 服务器上运行。有趣的是,我将旧应用程序的 Omniauth 配置处理到新应用程序,所以它一定是 Devise 的另一个模块出了问题……而不是 Omniauth 本身。

无论哪种情况,现在都可以使用。所以我会把它放在床上,并把它留在这里,以防其他人遇到同样的问题;虽然我不能说具体哪里出了问题,但这些是我用来解决 debug/fix 我的特定问题的步骤。

omniauth-github 我们遇到了同样的错误。为我们修复它(除了 provider_ignores_state: true hack)是 link 到 github 的身份验证站点中的 URL。最初我们为 github OAuth (https://github.com/login/oauth/authorize?client_id=#{ENV["GITHUB_CLIENT_ID"]}&scope=repo) 输入了整个 URL,但将其更改为仅 /auth/github 的 omniauth 格式修复了此 CSRF 错误(以及当我们尝试模拟/测试我们的 OAuth 时,没有发现路由错误)。把这个留在这里以防其他人将来遇到类似的问题!