1

我正在使用 Rails 构建社交登录,并且已成功将其与 Google 和 Facebook 集成。所以,我对 Twitter 也是如此。但是登录 Twitter 后我无法重定向到我的应用程序。我收到如下错误:

ActiveRecord::RecordInvalid in Users::OmniauthCallbacksController#twitter 验证失败:电子邮件不能为空,电子邮件不能为空,电子邮件无效

这是我在控制器中的代码:

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    generic_callback("facebook")
  end

  def google_oauth2
    generic_callback("google_oauth2")
  end

  def twitter
    generic_callback("twitter")
  end

  def generic_callback provider
    @user = User.from_omniauth(request.env["omniauth.auth"])
    if @user.persisted?
      log_in @user
      flash[:success] = t("users.new.welcome")
      redirect_to @user
    else
      flash[:error] = t("sessions.new.error")
      redirect_to root_url
    end
  end

  def failure
    redirect_to root_path
  end
end

模型中获取数据的部分代码

# Generate data from the social
  def self.from_omniauth(auth)
    user = User.where(email: auth.info.email).first
    password = Devise.friendly_token[0,20]
    user ||= User.create!(provider: auth.provider,
                           uid: auth.uid,
                           email: auth.info.email,
                           name: auth.info.name,
                           password: password,
                           password_confirmation: password)
  end

并在文件中配置 devise.rb

config.omniauth :google_oauth2, ENV["CLIENT_ID"], ENV["CLIENT_SECRET"], scope: "email", info_fields: "email,name"
config.omniauth :facebook, ENV["FACEBOOK_ID"], ENV["FACEBOOK_SECRET"], scope: "email", info_fields: "email,name"
config.omniauth :twitter, ENV["TWITTER_ID"], ENV["TWITTER_SECRET"], scope: "email", info_fields: "email,name"
4

1 回答 1

0

默认情况下,Devise 用户需要电子邮件。您看到的错误是验证失败,因为您没有收到来自 Twitter 的回复中的电子邮件。(您没有显示实际 OAuth 请求的任何代码,但为了论证,我假设身份验证成功,并且您实际上获得了有效的响应,并将重定向回您的应用程序。)

根据Twitter API 文档,请求用户的电子邮件是一种提升权限:

developer.twitter.com 上的应用权限下提供了“向用户请求电子邮件地址”复选框。必须在应用程序设置中填写隐私政策 URL 和服务条款 URL 字段,电子邮件地址才能正常访问。如果启用,将通过 oauth/authorize 对话框通知用户您的应用可以访问他们的电子邮件地址。

此外,文档指出:

如果用户在他们的帐户上没有电子邮件地址,或者如果电子邮件地址没有经过验证,则将返回 null。

因此,您需要确保您的应用程序的权限配置正确以接收任何电子邮件,即使如此,您也不能依赖于接收电子邮件。

一种替代方法是在您的设计用户模型中禁用电子邮件验证,如下所示:

class User < ApplicationRecord
  ...
  def email_required?
    false
  end
end

编辑: Twitter API 要求调用者还明确要求提供帐户电子邮件(传递include_email=true请求)。查看中的代码omniauth-twitter——我假设你正在使用它——它确实这样做了,所以如果你的应用程序权限已配置并且帐户有一个经过验证的电子邮件,你应该得到它。

于 2021-08-01T04:35:53.740 回答