Rails, 设计 &Omniauth - 设置问题 [英] Rails, Devise & Omniauth - problems with setup

查看:35
本文介绍了Rails, 设计 &Omniauth - 设置问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试(再次)使用 Rails 4、devise 和 omniauth 设置身份验证.

我试着按照这篇文章中的例子:Rails 4,设计,Omniauth(具有多个提供商)

我安装了这些 gem:

gem '设计'宝石omniauth-google-oauth2"gem 'omniauth-facebook'gem 'omniauth-twitter'gem 'omniauth-linkedin-oauth2'宝石'oauth2'

我有一个用户模型和一个身份验证模型.

我有:

用户.rb:

 has_many :authentications绝对不赞成self.approved = false结尾def 批准self.approved = true结尾

社交 = {脸书: '脸书',google_oauth2: '谷歌',领英:'领英'}

def self.from_omniauth(auth, current_user)身份验证 = Authentication.where(:provider => auth.provider,:uid =>auth.uid.to_s,:token =>auth.credentials.token,:秘密 =>auth.credentials.secret).first_or_initializeauthentication.profile_page = auth.info.urls.first.last 除非 authentication.persisted?如果authentication.user.blank?用户 = current_user.nil??User.where('email = ?', auth['info']['email']).first : current_user如果user.blank?用户 = 用户.newuser.skip_confirmation!user.password = Devise.friendly_token[0, 20]user.fetch_details(auth)用户保存结尾authentication.user = 用户验证.保存结尾认证用户结尾def fetch_details(auth)self.first_name = auth.info.first_nameself.last_name = auth.info.last_nameself.email = auth.info.emailself.image = URI.parse(auth.info.image)结尾

身份验证.rb

belongs_to :user

Routes.rb

devise_for :users,:控制器 =>{:注册 =>"用户/注册",:omniauth_callbacks =>'用户/omniauth_callbacks',}

用户/注册_控制器

class Users::RegistrationsController <设计::注册控制器#before_filter :check_permissions , :only =>[ :new, :create, :cancel ]#skip_before_filter :require_no_authenticationdef check_permissions授权!:创建,资源结尾定义索引如果参数[:批准] ==假"@users = User.find_all_by_approved(false)别的@users = User.all结尾结尾定义创建@user = User.new(user_params) #(params[:user])response_to do |格式|如果resource.save# 告诉 UserMailer 保存后发送欢迎邮件# {@user.send_admin_mail# @user.send_user_welcome_mail}format.html { redirect_to(profile_path(@user.profile))}#,通知:'我们已收到您的注册.我们会尽快与您联系.') }#format.json { 渲染 json: root_path, status: :created, location: @user }别的#format.html { redirect_to(root_path, alert: '对不起!您的注册出现问题.请联系我们解决.') }format.html { 渲染动作:'新' }format.json { 渲染 json: @user.errors, 状态: :unprocessable_entity }结尾结尾结尾私人的定义用户参数params.require(:user).permit(:first_name, :last_name, :email, :password)结尾# 受保护# def after_sign_up_path_for(资源)#'订阅者/新'#   结尾结尾

用户/Omniauth_callbacks 控制器

class Users::OmniauthCallbacksController

设计::OmniauthCallbacksController

 # 按照 https://stackoverflow.com/questions/21249749/rails-4-devise-omniauth-with-multiple-providers 重试全部定义用户 = User.from_omniauth(env['omniauth.auth'], current_user)如果 user.persisted?登录用户flash[:notice] = t('devise.omniauth_callbacks.success', :kind => User::SOCIALS[params[:action].to_sym])如果 user.sign_in_count == 1重定向到 profile_path(@user.profile)别的重定向到 root_path结尾别的session['devise.user_attributes'] = user.attributes重定向到 root_path结尾结尾User::SOCIALS.each 做 |k, _|alias_method k, :all结尾结尾

设计/新注册视图说:

<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|%><div class="row"><div class="col-md-3 col-md-offset-3"><div class="row"><div class="col-md-12"><%- 如果 devise_mapping.omniauthable?%><div class="facebookauth"><%= link_to "加入 Facebook", user_omniauth_authorize_path(:facebook) %>

<%结束-%>

<div class="row"><div class="col-md-12"><%- 如果 devise_mapping.omniauthable?%><div class="googleauth"><%= link_to "加入 Google", user_omniauth_authorize_path(:google_oauth2) %>

<%结束-%>

<div class="row"><div class="col-md-12"><%- 如果 devise_mapping.omniauthable?%><div class="linkedinauth"><%= link_to "加入领英", user_omniauth_authorize_path(:linkedin) %>

<%结束-%>

<div class="row"><div class="col-md-12"><%- 如果 devise_mapping.omniauthable?%><div class="twitterauth"><%= link_to "加入推特", user_omniauth_authorize_path(:twitter) %>

<%结束-%>

<div class="col-md-5"><div class="emailform"><div class="form-inputs", style="margin-left: 7%"><%= devise_error_messages!%><%= f.input :first_name, :label_html =>{:class =>'deviselabels'},自动对焦:真,必需:假,:input_html =>{:maxlength =>15, :size =>40、类:'lineitemdevise'}%><%= f.input :last_name, :label_html =>{:class =>'deviselabels'},需要:false,:input_html =>{:maxlength =>15, :size =>40、类:'lineitemdevise'}%><%= f.input :email, :label_html =>{:class =>'deviselabels'},必需:false,自动对焦:false,占位符:请使用您的工作或大学地址",:input_html =>{:maxlength =>55, :size =>40、类:'lineitemdevise'}%><%= f.input :password, :label_html =>{:class =>'deviselabels'},必需:false,占位符:最少 8 个字符",:input_html =>{:maxlength =>15, :size =>40、类:'lineitemdevise'}%>

<div class="form-actions"><%= f.button :submit, "通过电子邮件加入", :class =>dcpb"%>

<%结束%>

我有另一个名为 profile.rb 的模型.

profile属于用户

问题:

  1. 这些都不行.当我点击每个社交媒体登录链接时,页面会跳转到通过电子邮件注册的表单.

heroku 日志错误消息说:

(facebook) 认证失败!invalid_credentials: OAuth2::Error, :2015-11-03T07:05:48.237549+00:00 app[web.1]: {"error":{"message":"验证验证码时出错.请确保您的redirect_uri与您在OAuth 对话请求","type":"OAuthException","code":100,"fbtrace_id":"HD3mnzmSTEw"}}

  1. 当我使用电子邮件和密码完成通过电子邮件形式的注册时,系统会识别出用户名(因为导航栏会显示 Hello ,但是当我进入 Rails 控制台时,该用户并未列出.

此外,当我单击用户名时,我收到一条错误消息,指出该配置文件不存在.heroku 日志说:

(找不到 'id'=3 的个人资料)

  1. 是否还需要其他步骤才能使社交媒体注册工作以创建新用户?

我的下一次尝试:

我已经按照 Railscasts 视频中的方法更改了上述所有内容并再次尝试.

我现在使用用户模型和身份验证模型.

在 user.rb 中,我有:

 has_many :authentications, :dependent =>:删除所有def apply_omniauth(omniauth)authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'], :token => auth['credentials']['token'])结尾

身份验证.rb

belongs_to :userdef self.from_omniauth(auth)where(auth.slice(:provider, :uid)).first_or_create 做 |用户 |authentication.provider = auth.provider身份验证.uid = auth.uidauthentication.user.first_name = auth.first_nameauthentication.user.last_name = auth.last_nameauthentication.user.image = auth.info.image结尾结尾

Authentications_controller:

class AuthenticationsController <应用控制器before_action :set_authentication, only: [:destroy]定义索引@authentications = current_user.authentications if current_user结尾定义创建omn​​iauth = request.env["omniauth.auth"]身份验证 = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])如果认证sign_in_and_redirect_user(:user, authentication.user.profile)elsif current_usercurrent_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])重定向到 user.profile_url别的用户 = 用户.newuser.omniauth(omniauth)如果用户.保存!sign_in_and_redirect_user(:user, user.profile)别的session[:omniauth] = omniauth.except('额外')redirect_to new_user_registration_url结尾结尾结尾销毁@authentication.destroyresponse_to do |格式|format.html { redirect_to authentications_url }format.json { 头:no_content }结尾结尾私人的# 使用回调在动作之间共享公共设置或约束.def set_authentication@authentication = current_user.authentications.find(params[:id])结尾结尾

在 routes.rb 中,我有:

 devise_for :users,:控制器 =>{:注册 =>"用户/注册",}补丁 '/auth/:provider/callback' =>'身份验证#创建'

Omniauth.rb

需要'omniauth-facebook'需要'omniauth-google-oauth2'

OmniAuth.config.logger = Rails.logger

 Rails.application.config.middleware.use OmniAuth::Builder 做提供者:facebook,ENV['FACEBOOK_ID'],ENV['FACEBOOK_KEY'],:范围=>'public_profile', info_fields: 'id,first_name,last_name,link,email',:显示 =>'弹出',:client_options =>{:ssl =>{:ca_file =>'/usr/lib/ssl/certs/ca-certificates.crt'}}

然后当我尝试这个时,我得到这个错误:

(facebook) 认证失败!invalid_credentials: OAuth2::Error, :2015-11-05T06:4839+00:00 app[web.1]: {"error":{"message":"验证验证码时出错.请确保您的 redirect_uri 与您在 OAuth 对话框中使用的相同request","type":"OAuthException","code":100,"fbtrace_id":"CrvXN22Z"}}

我发现错误消息的下一部分很奇怪,因为它指的是我不再使用的回调控制器(整个内容都被注释掉了,没有路由).

认证失败!invalid_credentials: OAuth2::Error, :2015-11-05T08:24:16.010951+00:00 app[web.1]: 由 Devise::OmniauthCallbacksController#failure 处理为 HTML2015-11-05T08:24:16.012648+00:00 应用程序[web.1]:重定向到 http://www.dder.com/users/sign_in

进一步的尝试

1.5 年多以来,我一直在尝试使用 omniauth 设置设计.这是我的最新尝试(遵循 sitepoint.com/rails-authentication-oauth-2-0-omniauth 上的 Sitepoint 教程).我之前曾尝试使用本教程但没有取得任何成功,因此我进行了一些调整以尝试将其调整到有关此主题的其他教程的某些方面.

我现在有:

用户.rb

 has_many :authentications, :dependent =>:删除所有def apply_omniauth(omniauth)authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'], :token => auth['credentials']['token'])结尾

身份验证.rb

belongs_to :userdef self.from_omniauth(auth)where(auth.slice(:provider, :uid)).first_or_create 做 |用户 |authentication.provider = auth.provider身份验证.uid = auth.uidauthentication.user.first_name = auth.first_nameauthentication.user.last_name = auth.last_nameauthentication.user.image = auth.info.image结尾结尾

身份验证控制器

 类 AuthenticationsController <;设计::OmniauthCallbacksControllerbefore_action :set_authentication, only: [:destroy]定义索引@authentications = current_user.authentications if current_user结尾定义创建omn​​iauth = request.env["omniauth.auth"]身份验证 = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])如果认证sign_in_and_redirect_user(:user, authentication.user.profile)elsif current_usercurrent_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])重定向到 user.profile_url别的用户 = 用户.newuser.omniauth(omniauth)如果用户.保存!sign_in_and_redirect_user(:user, user.profile)别的session[:omniauth] = omniauth.except('额外')redirect_to new_user_registration_url结尾结尾结尾销毁@authentication.destroyresponse_to do |格式|format.html { redirect_to authentications_url }format.json { 头:no_content }结尾结尾私人的# 使用回调在动作之间共享公共设置或约束.def set_authentication@authentication = current_user.authentications.find(params[:id])结尾结尾

注册控制器

class Users::RegistrationsController <设计::注册控制器#before_filter :check_permissions , :only =>[ :new, :create, :cancel ]#skip_before_filter :require_no_authentication# before_action :configure_permitted_pa​​rameters, if: :devise_controller?# 来自 Sitepoint 教程的建议 - 当前未实施,因为不确定 this 和 set params 之间的区别.def check_permissions授权!:创建,资源结尾定义索引如果参数[:批准] ==假"@users = User.find_all_by_approved(false)别的@users = User.all结尾结尾定义创建极好的session[:omniauth] = nil 除非@user.new_record?结尾# 这是来自 SITEPOINT 教程的建议# 受保护# def configure_permitted_pa​​rameters# devise_parameter_sanitizer.for(:sign_up) <<[:first_name, :last_name]#   结尾私人的定义用户参数params.require(:user).permit(:first_name, :last_name, :email, :password)结尾def build_resource(*args)极好的如果会话[:omniauth]@user.apply_omniauth(会话[:omniauth])@user.valid?结尾结尾结尾

路线

devise_for :users,:控制器 =>{:注册 =>"用户/注册",:omniauth_callbacks =>认证"# :omniauth_callbacks =>'用户/omniauth_callbacks',}get '/auth/:provider/callback' =>'身份验证#创建'

我可以通过以下方式检查这些路线:

rake 路线 |授权user_omniauth_authorize GET|POST/users/auth/:provider(.:format) authentications#passthru {:provider=>/facebook|linkedin|twitter|google_oauth2/}user_omniauth_callback GET|POST/users/auth/:action/callback(.:format) authentications#:actionGET/auth/:provider/callback(.:format) 认证#create

视图中的新注册部分

<%- 如果 devise_mapping.omniauthable?%><div class="twitterauth"><%= link_to "加入推特", user_omniauth_authorize_path(:twitter) %>

<%结束-%>

我真的不确定这条路是从哪里来的.不知道为什么这么命名.

视图中的新会话部分

 <%- 如果 devise_mapping.omniauthable?%><div class="twitterauth"><%= link_to "用推特登录", user_omniauth_authorize_path(:twitter) %>

<%结束-%>

当前错误:

AbstractController::ActionNotFound at/users/auth/twitter/callback无法为 AuthenticationsController 找到操作twitter"

解决方案

Devise 带有一个开箱即用的解决方案,用于与 omniuth 集成.您可以查看这些网址:1. https:///www.digitalocean.com/community/tutorials/how-to-configure-devise-and-omniauth-for-your-rails-application这个展示了与 DigitalOcean 的集成,但可以扩展到其他人.2. https://github.com/plataformatec/devise/wiki/OmniAuth%3A-概述这是来自devise wiki

希望能帮到你

I am trying (again) to set up authentications with Rails 4, devise and omniauth.

I tried to follow the example in this post: Rails 4, Devise, Omniauth (with multiple providers)

I have these gems installed:

gem 'devise'
gem 'omniauth-google-oauth2'
gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'omniauth-linkedin-oauth2'
gem 'oauth2'

I have a user model, and an authentications model.

I have:

User.rb:

  has_many :authentications

def disapprove
    self.approved = false
  end

  def approve
    self.approved = true
  end

SOCIALS = { facebook: 'Facebook', google_oauth2: 'Google', linkedin: 'Linkedin' }

def self.from_omniauth(auth, current_user)
  authentication = Authentication.where(:provider => auth.provider,
                                  :uid => auth.uid.to_s, 
                                  :token => auth.credentials.token, 
                                  :secret => auth.credentials.secret).first_or_initialize
  authentication.profile_page = auth.info.urls.first.last unless authentication.persisted?
  if authentication.user.blank?
    user = current_user.nil? ? User.where('email = ?', auth['info']['email']).first : current_user
    if user.blank?
      user = User.new
      user.skip_confirmation!
      user.password = Devise.friendly_token[0, 20]
      user.fetch_details(auth)
      user.save
    end
    authentication.user = user
    authentication.save
  end
  authentication.user 
end  

def fetch_details(auth)
  self.first_name = auth.info.first_name
  self.last_name = auth.info.last_name
  self.email = auth.info.email
  self.image = URI.parse(auth.info.image)
end

Authentication.rb

 belongs_to :user

Routes.rb

devise_for :users,
             :controllers => {
:registrations => "users/registrations",


             :omniauth_callbacks => 'users/omniauth_callbacks',
           }

User/registrations_controller

class Users::RegistrationsController < Devise::RegistrationsController 
  #before_filter :check_permissions , :only => [ :new, :create, :cancel ] 
  #skip_before_filter :require_no_authentication 

  def check_permissions
    authorize! :create, resource
  end

  def index
    if params[:approved] == "false"
      @users = User.find_all_by_approved(false)
    else
      @users = User.all
    end
  end

    def create
        @user = User.new(user_params) #(params[:user])

        respond_to do |format|
          if resource.save
            # Tell the UserMailer to send a welcome email after save
            # {@user.send_admin_mail
            # @user.send_user_welcome_mail}

            format.html { redirect_to(profile_path(@user.profile))}
            #, notice: 'We have received your registration. We will be in touch shortly.') }
            #format.json { render json: root_path, status: :created, location: @user }
          else
            #format.html { redirect_to(root_path, alert: 'Sorry! There was a problem with your registration. Please contact us to sort it out.') }
            format.html { render action: 'new' }
            format.json { render json: @user.errors, status: :unprocessable_entity }
          end
        end
      end

      private
      def user_params
          params.require(:user).permit(:first_name, :last_name, :email, :password )
        end



      # protected
      #   def after_sign_up_path_for(resource)
      #     'subscribers/new'
      #   end
end

User/Omniauth_callbacks controller

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

    # try again following https://stackoverflow.com/questions/21249749/rails-4-devise-omniauth-with-multiple-providers

  def all
    user = User.from_omniauth(env['omniauth.auth'], current_user)
    if user.persisted?
      sign_in user
      flash[:notice] = t('devise.omniauth_callbacks.success', :kind => User::SOCIALS[params[:action].to_sym])
      if user.sign_in_count == 1
        redirect_to profile_path(@user.profile)
      else
        redirect_to root_path
      end
    else
      session['devise.user_attributes'] = user.attributes
      redirect_to root_path
    end
  end

  User::SOCIALS.each do |k, _|
    alias_method k, :all
  end
end

The devise/new registrations view says:

<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>

    <div class="row">
        <div class="col-md-3 col-md-offset-3">
            <div class="row">
                <div class="col-md-12">

                  <%- if devise_mapping.omniauthable? %>
                          <div class="facebookauth">
                            <%= link_to "Join with Facebook", user_omniauth_authorize_path(:facebook) %>
                          </div>
                  <% end -%>

                </div>
              </div>


          <div class="row">
            <div class="col-md-12">

              <%- if devise_mapping.omniauthable? %>
                  <div class="googleauth">
                    <%= link_to "Join with Google", user_omniauth_authorize_path(:google_oauth2) %>
                  </div>
              <% end -%>
            </div>
          </div>



      <div class="row">
              <div class="col-md-12">

                  <%- if devise_mapping.omniauthable? %>
                      <div class="linkedinauth">
                        <%= link_to "Join with LinkedIn", user_omniauth_authorize_path(:linkedin) %>
                      </div>
                  <% end -%>
              </div>
      </div>

          <div class="row">
            <div class="col-md-12">

              <%- if devise_mapping.omniauthable? %>
                  <div class="twitterauth">
                    <%= link_to "Join with Twitter", user_omniauth_authorize_path(:twitter) %>
                  </div>
              <% end -%>

            </div>
          </div>

        </div>

        <div class="col-md-5">
          <div class="emailform">
            <div class="form-inputs", style="margin-left: 7%">


                  <%= devise_error_messages! %>
                  <%= f.input :first_name,  :label_html => {:class => 'deviselabels'}, autofocus: true, required: false, :input_html => {:maxlength => 15, :size => 40, class: 'lineitemdevise'} %>
                  <%= f.input :last_name, :label_html => {:class => 'deviselabels'}, required: false, :input_html => {:maxlength => 15, :size => 40, class: 'lineitemdevise'} %>
                  <%= f.input :email, :label_html => {:class => 'deviselabels'}, required: false, autofocus: false, placeholder: "Please use your work or university address", :input_html => {:maxlength => 55, :size => 40, class: 'lineitemdevise'} %>
                  <%= f.input :password, :label_html => {:class => 'deviselabels'}, required: false, placeholder: "Minimum 8 characters", :input_html => {:maxlength => 15, :size => 40, class: 'lineitemdevise'} %>
                </div>

            <div class="form-actions">
          <%= f.button :submit, "Join by email", :class => "dcpb" %>
         </div>
          <% end %>
          </div>
      </div>

I have another model called profile.rb.

profile belongs_to user

Problems:

  1. None of this works. When I click on each of the social media login links, the page just jumps to the sign up by email form.

The heroku logs error message says:

(facebook) Authentication failure! invalid_credentials: OAuth2::Error, : 
2015-11-03T07:05:48.237549+00:00 app[web.1]: {"error":{"message":"Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request","type":"OAuthException","code":100,"fbtrace_id":"HD3mnzmSTEw"}}

  1. When I complete the sign up by email form with an email and password, the user name is recognised (in that the navbar says Hello , but when I go into the rails console, the user is not listed.

Also, when I click on the user name, I get an error which says that profile does not exist. The heroku logs say:

(Couldn't find Profile with 'id'=3)

  1. Is there another step required to make the social media registrations work to create a new user?

MY NEXT ATTEMPT:

I've changed all of the above and tried again, following the approach in the Railscasts videos.

I now use a user model and an authentications model.

In the user.rb, I have:

  has_many :authentications, :dependent => :delete_all

def apply_omniauth(omniauth)
      authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'], :token => auth['credentials']['token'])

end

authentication.rb

belongs_to :user

def self.from_omniauth(auth)
    where(auth.slice(:provider, :uid)).first_or_create do | user |
        authentication.provider = auth.provider
        authentication.uid = auth.uid
        authentication.user.first_name = auth.first_name
        authentication.user.last_name = auth.last_name
        authentication.user.image = auth.info.image

    end
  end

Authentications_controller:

class AuthenticationsController < ApplicationController
  before_action :set_authentication, only: [:destroy]

  def index
    @authentications = current_user.authentications if current_user
  end


  def create
    omniauth = request.env["omniauth.auth"]
    authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
    if authentication
      sign_in_and_redirect_user(:user, authentication.user.profile)

    elsif current_user
      current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
      redirect_to user.profile_url
    else
      user = User.new
      user.omniauth(omniauth)
      if user.save!
        sign_in_and_redirect_user(:user, user.profile)
      else
        session[:omniauth] = omniauth.except('extra')
        redirect_to new_user_registration_url
      end
    end  
  end

  def destroy
    @authentication.destroy
    respond_to do |format|
      format.html { redirect_to authentications_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_authentication
      @authentication = current_user.authentications.find(params[:id])
    end
end

In the routes.rb, I have:

 devise_for :users,
             :controllers => {
                :registrations => "users/registrations",
           }
 patch '/auth/:provider/callback' => 'authentications#create'

Omniauth.rb

require 'omniauth-facebook' require 'omniauth-google-oauth2'

OmniAuth.config.logger = Rails.logger

 Rails.application.config.middleware.use OmniAuth::Builder do
   provider :facebook, ENV['FACEBOOK_ID'], ENV['FACEBOOK_KEY'],
     :scope => 'public_profile', info_fields: 'id,first_name,last_name,link,email',
     :display => 'popup',
     :client_options => {:ssl => {:ca_file => '/usr/lib/ssl/certs/ca-certificates.crt'}}

Then when I try this, I get this error:

(facebook) Authentication failure! invalid_credentials: OAuth2::Error, : 
2015-11-05T06:4839+00:00 app[web.1]: {"error":{"message":"Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request","type":"OAuthException","code":100,"fbtrace_id":"CrvXN22Z"}}

I find the next part of the error message odd because it refers to the callbacks controller which I no longer use (the whole thing is commented out and there is no route for it).

Authentication failure! invalid_credentials: OAuth2::Error, : 
2015-11-05T08:24:16.010951+00:00 app[web.1]: Processing by Devise::OmniauthCallbacksController#failure as HTML
2015-11-05T08:24:16.012648+00:00 app[web.1]: Redirected to http://www.dder.com/users/sign_in

A FURTHER ATTEMPT

I have been trying to set up devise with omniauth for more than 1.5 years now. This is my latest attempt (following the Sitepoint tutorial at sitepoint.com/rails-authentication-oauth-2-0-omniauth). I've tried to use this tutorial before and not had any success, so I've made some tweaks to try and adapt it to some aspects of other tutorials on this topic.

I now have:

user.rb

  has_many :authentications, :dependent => :delete_all

def apply_omniauth(omniauth)
      authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'], :token => auth['credentials']['token'])

  end

authentication.rb

belongs_to :user
  def self.from_omniauth(auth)
    where(auth.slice(:provider, :uid)).first_or_create do | user |
        authentication.provider = auth.provider
        authentication.uid = auth.uid
        authentication.user.first_name = auth.first_name
        authentication.user.last_name = auth.last_name
        authentication.user.image = auth.info.image

    end
  end

authentications controller

    class AuthenticationsController < Devise::OmniauthCallbacksController
      before_action :set_authentication, only: [:destroy]

      def index
        @authentications = current_user.authentications if current_user
      end


      def create
        omniauth = request.env["omniauth.auth"]
        authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
        if authentication
          sign_in_and_redirect_user(:user, authentication.user.profile)

        elsif current_user
          current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
          redirect_to user.profile_url
        else
          user = User.new
          user.omniauth(omniauth)
          if user.save!
            sign_in_and_redirect_user(:user, user.profile)
          else
            session[:omniauth] = omniauth.except('extra')
            redirect_to new_user_registration_url
          end
        end  
      end

      def destroy
        @authentication.destroy
        respond_to do |format|
          format.html { redirect_to authentications_url }
          format.json { head :no_content }
        end
      end

      private
        # Use callbacks to share common setup or constraints between actions.
        def set_authentication
          @authentication = current_user.authentications.find(params[:id])
        end
    end

registrations controller

class Users::RegistrationsController < Devise::RegistrationsController 
  #before_filter :check_permissions , :only => [ :new, :create, :cancel ] 
  #skip_before_filter :require_no_authentication 
  # before_action :configure_permitted_parameters, if: :devise_controller? # Suggestion from Sitepoint tutorial - not currently implemented because not sure about the difference between this and set params.

  def check_permissions
    authorize! :create, resource
  end

  def index
    if params[:approved] == "false"
      @users = User.find_all_by_approved(false)
    else
      @users = User.all
    end
  end

  def create
    super
    session[:omniauth] = nil unless @user.new_record?
  end

  # THIS IS A SUGGESTION FROM SITEPOINT TUTORIAL 
  # protected

  #   def configure_permitted_parameters
  #     devise_parameter_sanitizer.for(:sign_up) << [:first_name, :last_name]
  #   end


  private
    def user_params
          params.require(:user).permit(:first_name, :last_name, :email, :password )
    end

    def build_resource(*args)
        super
        if session[:omniauth]
        @user.apply_omniauth(session[:omniauth])
        @user.valid?
        end
    end  

end

routes

devise_for :users,
             :controllers => {
                :registrations => "users/registrations",
                :omniauth_callbacks => "authentications"
                # :omniauth_callbacks => 'users/omniauth_callbacks',
           }

get '/auth/:provider/callback' => 'authentications#create'

I can check these routes with:

rake routes | grep auth
                      user_omniauth_authorize GET|POST /users/auth/:provider(.:format)                                                                 authentications#passthru {:provider=>/facebook|linkedin|twitter|google_oauth2/}
                       user_omniauth_callback GET|POST /users/auth/:action/callback(.:format)                                                          authentications#:action
                                              GET      /auth/:provider/callback(.:format)                                                              authentications#create

new registration partial in the view

<%- if devise_mapping.omniauthable? %>
                  <div class="twitterauth">
                    <%= link_to "Join with Twitter", user_omniauth_authorize_path(:twitter) %>
                  </div>
              <% end -%>

I'm really not sure where this path is coming from. Not sure why it's named as it is.

new session partial in the view

 <%- if devise_mapping.omniauthable? %>
                  <div class="twitterauth">
                    <%= link_to "Login with Twitter", user_omniauth_authorize_path(:twitter) %>
                  </div>
              <% end -%>

Current error:

AbstractController::ActionNotFound at /users/auth/twitter/callback

The action 'twitter' could not be found for AuthenticationsController

解决方案

Devise comes with an out of the box solution for integration with omniuth. You can checkout these urls: 1. https://www.digitalocean.com/community/tutorials/how-to-configure-devise-and-omniauth-for-your-rails-application This one shows integration with DigitalOcean but can be extended to others. 2. https://github.com/plataformatec/devise/wiki/OmniAuth%3A-Overview This one is from devise wiki

Hope it helps

这篇关于Rails, 设计 &amp;Omniauth - 设置问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆