Heroku +设计 1.2 + OmniAuth 到 GitHub = “电子邮件”列中的空值

发布于 2024-10-16 04:23:12 字数 3270 浏览 3 评论 0原文

我正在尝试设置 Devise 1.2 以允许通过 GitGub 进行用户身份验证。据我可以使用 Cucumber 在本地测试它,并删除 GitHub OAuth,它似​​乎工作正常。然而,在部署到 Heroku 并尝试进行身份验证后,从 GitHub 重定向回我的应用程序后出现错误。

检查 Heroku 日志,我看到的错误是...

PGError: ERROR: null value in column "email"违反了非空约束

所以显然,我要么没有从 GitHub 得到电子邮件地址,要么它在某个地方丢失了一路上?

我已按照 https://github.com/plataformatec/devise 上的说明和示例进行操作/wiki/OmniAuth:-概述https://github.com/plataformatec/devise/wiki/OmniAuth:--Testing-%27facebook%27-signup--% 5BRails-3---Cucumber---Capybara---Mongoid-%5D,但针对 GitHub 而不是 Facebook 进行了修改,参考 GitHub 策略的 OmniAuth 源代码 https://github.com/intridea/omniauth/blob/master/ oa-oauth/lib/omniauth/strategies/github.rb

这是我的 devise_steps.rb 文件,它会导致传递 Cucumber 功能:

ACCESS_TOKEN = {
  :access_token => "stevejdev"
}

# Not all pieces of this hash are yet proven to be correct.
# It does, at least supply the necessary information for a
# successful login simulation though.
GITHUB_INFO = {
  :user => {
    :id => '12345', 
    :email => '[email protected]',
    # login value maps to nickname and to <user> part of
    # "http://github.com/<user>" in urls[GitHub]
    :login => 'johnxd',
    :name => 'John Doe',
    # blog value maps to urls[blog]
    :blog => 'http://blaagstop.com/johndoe',
  }
}

When /^GitHub replies$/ do 
  Devise::OmniAuth.short_circuit_authorizers!
  Devise::OmniAuth.stub!(:github) do |b|
    b.post('/login/oauth/access_token') { 
              [200, {}, ACCESS_TOKEN.to_json] }
    b.get('/api/v2/json/user/show?access_token=stevejdev') {
              [200, {}, GITHUB_INFO.to_json ] }
  end

  visit user_omniauth_callback_path(:github)
end

这是我的回调处理程序:

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  def github
    @user = User.find_for_github_oauth(env["omniauth.auth"], current_user)

    if @user.persisted?
      flash[:notice] = I18n.t(
        "devise.omniauth_callbacks.success", :kind => "GitHub" )
      sign_in_and_redirect @user, :event => :authentication
    else
      session["devise.github_data"] = env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

end

这是我的用户模型中的 find_for_github_oauth 定义:

def self.find_for_github_oauth(access_token, signed_in_resource=nil)
  data = access_token['extra']['user_hash']

  # Find the existing user or create a new one.
  #  Omit the password-generation code shown in the example at
  #  https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
  #  because we're intending to use OmniAuth only, so
  #  presumably don't need a password.
  User.find_by_email( data["email"] ) ||
  User.create!( :email => data["email"] )

end

I'm trying to set up Devise 1.2 to allow user authentication via GitGub. As far as I can test it locally using Cucumber, and stubbing out GitHub OAuth, it seems to be working fine. After I deploy to Heroku, however, and try to authenticate, I get an error after being redirected back to my application from GitHub.

Checking the Heroku log, the error I see is...

PGError: ERROR: null value in column "email" violates not-null constraint

So apparently, I'm either not getting an email address back from GitHub, or it's being lost somewhere along the way?

I've followed the instructions and examples on https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview and https://github.com/plataformatec/devise/wiki/OmniAuth:--Testing-%27facebook%27-signup--%5BRails-3---Cucumber---Capybara---Mongoid-%5D, but modified them for GitHub instead of Facebook, referring to the OmniAuth source code for the GitHub strategy at https://github.com/intridea/omniauth/blob/master/oa-oauth/lib/omniauth/strategies/github.rb.

Here's what I have for my devise_steps.rb file, which results in a passing Cucumber feature:

ACCESS_TOKEN = {
  :access_token => "stevejdev"
}

# Not all pieces of this hash are yet proven to be correct.
# It does, at least supply the necessary information for a
# successful login simulation though.
GITHUB_INFO = {
  :user => {
    :id => '12345', 
    :email => '[email protected]',
    # login value maps to nickname and to <user> part of
    # "http://github.com/<user>" in urls[GitHub]
    :login => 'johnxd',
    :name => 'John Doe',
    # blog value maps to urls[blog]
    :blog => 'http://blaagstop.com/johndoe',
  }
}

When /^GitHub replies$/ do 
  Devise::OmniAuth.short_circuit_authorizers!
  Devise::OmniAuth.stub!(:github) do |b|
    b.post('/login/oauth/access_token') { 
              [200, {}, ACCESS_TOKEN.to_json] }
    b.get('/api/v2/json/user/show?access_token=stevejdev') {
              [200, {}, GITHUB_INFO.to_json ] }
  end

  visit user_omniauth_callback_path(:github)
end

Here's my callback handler:

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  def github
    @user = User.find_for_github_oauth(env["omniauth.auth"], current_user)

    if @user.persisted?
      flash[:notice] = I18n.t(
        "devise.omniauth_callbacks.success", :kind => "GitHub" )
      sign_in_and_redirect @user, :event => :authentication
    else
      session["devise.github_data"] = env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

end

Here's the find_for_github_oauth definition in my User model:

def self.find_for_github_oauth(access_token, signed_in_resource=nil)
  data = access_token['extra']['user_hash']

  # Find the existing user or create a new one.
  #  Omit the password-generation code shown in the example at
  #  https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
  #  because we're intending to use OmniAuth only, so
  #  presumably don't need a password.
  User.find_by_email( data["email"] ) ||
  User.create!( :email => data["email"] )

end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

染年凉城似染瑾 2024-10-23 04:23:12

事实证明,问题在于 GitHub 不使用电子邮件地址作为用户标识符,并且根本不需要在令牌中包含电子邮件值。我通过使用登录名而不是电子邮件地址解决了该问题。

由于我计划将来支持多个提供商,因此我现在使用 auth_providerlogin 字段的组合作为 users< /code> 表,并且我在 config/devise.rb 文件中指定了 config.authentication_keys = [ :auth_provider, :login ] 。当我添加对另一个使用电子邮件地址进行用户登录的提供商的支持时,这很好。我将仅使用提供商响应中的电子邮件值作为模型的登录值。

It turns out the problem is that GitHub does not use the email address as the user identifier, and does not necessarily include the email value in the token at all. I solved the problem by using the login instead of the email address.

Since I'm planning to support multiple providers in the future, I'm now using a combination of auth_provider and login fields as the logical key for the users table, and I've specified config.authentication_keys = [ :auth_provider, :login ] in the config/devise.rb file. When I'm adding support for another provider that does use an email address for the user's login, that's fine. I'll just use the email value from the provider's response as the login value for the model.

一花一树开 2024-10-23 04:23:12

对于后代:

此问题已在omniauth-github gem 存储库中解决,位于 此合并

它在最新版本中不可用,所以如果你想拥有它,你必须通过将 repo 地址添加到你的 gemfile 来获取最前沿的 repo 版本:

gem 'omniauth-github', :git => "git://github.com/intridea/omniauth-github.git"

For posterity:

This issue has been resolved in the omniauth-github gem repo, in this merge.

It's not available in the latest version, so if you want to have it, you have to get the cutting-edge repo version by adding the repo address to your gemfile:

gem 'omniauth-github', :git => "git://github.com/intridea/omniauth-github.git"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文