首页 > 解决方案 > ReactJs Web 客户端 + Ruby-on-Rails API 服务器 - 使用 Devise + OmniAuth 通过 facebook 和 google_oauth2 进行身份验证

问题描述

在客户端,我可以使用 OmniAuth 连接到 facebook 或 google_oauth2。但是在服务器端,我有一个Authentication failure!(出于不同的原因,取决于身份验证类型)。

我按照设计指南与 Omniauth 集成(此处),在集成到 Rails API(此处)时考虑了 Omniauth 的建议。

---反应应用---

src/components/socialAuth/SocialAuth.jsx

import React from 'react'
import FacebookLogin from 'react-facebook-login'
import GoogleLogin from 'react-google-login'

export default ({ handleLogInWithProvider }) => {
  const responseFacebook = response => {
    console.log('facebook', response)
    handleLogInWithProvider('facebook', response)
  }

  const responseGoogle = response => {
    console.log('google_oauth2', response)
    handleLogInWithProvider('google_oauth2', response)
  }

  return (
    <div className="social-auth">
      <FacebookLogin
        appId="XXXXXX"
        autoLoad={true}
        scope="email,public_profile"
        fields="email,name,picture"
        callback={responseFacebook}
      />
      <GoogleLogin
        clientId="XXXXXX"
        responseType="code"
        onSuccess={responseGoogle}
      />
    </div>
  )
}

src/ducks/auth.js

export const logInWithProvider = (provider, response) => async dispatch => {
  const endpoint = `/users/auth/${provider}/callback`
  const options = {
    method: 'POST',
    body: JSON.stringify(response),
    headers: {
      'Content-Type': 'application/json'
    }
  }

  try {
    const responseAPI = await dispatch(fetch({ endpoint, options }))
    console.log(responseAPI)
  } catch (error) {
    console.log(error)
  }
}

控制台显示 Facebook 和 Google 都返回一个完整的哈希(带有凭据和用户个人资料信息)......

---RoR API---

宝石文件

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

配置/初始化程序/devise.rb

  # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  facebook_app_id = Rails.application.credentials
                         .apis[:facebook][:oauth2][:app_id]
  facebook_app_secret = Rails.application.credentials
                             .apis[:facebook][:oauth2][:app_secret]
  google_app_id = Rails.application.credentials
                       .apis[:google][:oauth2][:app_id]
  google_app_secret = Rails.application.credentials
                           .apis[:google][:oauth2][:app_secret]

  # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
  config.omniauth :facebook,
                  facebook_app_id,
                  facebook_app_secret,
                  scope: 'email'
  config.omniauth :google_oauth2,
                  google_app_id,
                  google_app_secret,
                  name: 'google',
                  # Temporary fix for `Authentication failure! csrf_detected`...
                  provider_ignores_state: Rails.env.development?

应用程序/配置/应用程序.rb

    # To integrate OmniAuth into a Rails API.
    config.session_store :cookie_store, key: '_interslice_session'
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use ActionDispatch::Session::CookieStore, config.session_options

应用程序/模型/user.rb

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, omniauth_providers: %i[facebook google_oauth2]

配置/路由.rb

  devise_for :users,
             only: :omniauth_callbacks,
             controllers: { omniauth_callbacks: 'v1/omniauth_callbacks' }

应用程序/控制器/v1/omniauth_callbacks_controller.rb

module V1
  class OmniauthCallbacksController < Devise::OmniauthCallbacksController
    def facebook
      handle_omniauth
    end

    def google
      handle_omniauth
    end

    private

    # Provide central callback for OmniAuth.
    def handle_omniauth
      puts auth
      ...
    end

    def auth
      request.env['omniauth.auth']
    end
  end
end

在 Rails 控制台中,当我使用 Google 的一次性代码流(混合身份验证)请求不同的身份验证策略时,我会为 Facebook 和 Google 提供不同的错误消息。

ERROR -- omniauth: (facebook) Authentication failure! no_authorization_code: OmniAuth::Strategies::Facebook::NoAuthorizationCodeError, must pass either a `code` (via URL or by an `fbsr_XXX` signed request cookie)
ERROR -- omniauth: (google_oauth2) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected

我通过添加 Devise 初始化程序找到了一种解决方法,provider_ignores_state: true但它似乎并不安全......

配置/初始化程序/devise.rb

    config.omniauth :google_oauth2,
                  google_app_id,
                  google_app_secret,
                  name: 'google',
                  # Temporary fix for `Authentication failure! csrf_detected`...
                  provider_ignores_state: Rails.env.development?

标签: ruby-on-railsreactjsauthenticationdeviseomniauth

解决方案


推荐阅读