ruby-on-rails - 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?
解决方案
推荐阅读
- python - 根据 dateTime 创建子组
- flutter - 如何在颤动的第一行文本之前添加竖线?
- excel-formula - 前几个季度的excel公式
- html - 如何删除样式
- javascript - ag-grid 打印不适用于自定义渲染的单元格(使用“cellRenderer”)
- ibm-doors - 使用模块填充列表并将其显示在 DOORS 的对话框中
- swift - SwiftUI,在 .padding 上使用带有布尔值的尾随
- flutter - 有没有办法在 Flutter 中制作 Amazon Prime 视频播放器?
- sql - 即使 SQL 查询不返回任何结果,也将 varchar 转换为十进制时出错
- android - Android UI - 动态按钮对齐更改