You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 7 API-only集成Devise+Omniauth Google OAuth:current_user为nil求助

Omniauth Google + Rails API 认证问题解决方案

核心问题定位

你遇到的authenticate_user!未授权、session显示「#<ActionDispatch::Request::Session:0x197a8 not yet loaded>」的问题,本质是Rails API默认禁用Cookie Session,而Omniauth/Devise默认依赖Cookie存储认证状态,但API场景下需用Token认证替代Cookie。

解决步骤

1. 配置Devise启用Token认证

修改config/initializers/devise.rb,开启HTTP Token认证支持:

Devise.setup do |config|
  # 保留原有配置,新增以下内容
  config.http_authenticatable = true
  config.http_authenticatable_on_xhr = true
  config.token_authentication_key = 'access-token' # 自定义请求头的Token键名
end

2. 为User模型添加Token存储字段

生成迁移并执行:

rails generate migration AddAuthenticationTokenToUsers authentication_token:string:index
rails db:migrate

更新app/models/user.rb,自动生成并维护认证Token:

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, omniauth_providers: [:google_oauth2]

  before_save :ensure_authentication_token

  def ensure_authentication_token
    self.authentication_token = generate_authentication_token if authentication_token.blank?
  end

  private

  def generate_authentication_token
    loop do
      token = Devise.friendly_token
      break token unless User.exists?(authentication_token: token)
    end
  end
end

3. 调整Omniauth回调逻辑,返回自定义Token

修改app/controllers/users/omniauth_callbacks_controller.rb,禁用Cookie存储,返回自有API Token:

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google_oauth2
    user = User.from_omniauth(request.env["omniauth.auth"])
    if user.persisted?
      sign_in(user, store: false) # 关闭Cookie存储
      # 可将Google的refresh_token存入User模型,用于后续刷新Google access_token
      user.update(refresh_token: request.env["omniauth.auth"].credentials.refresh_token)
      render json: {
        user: user,
        access_token: user.authentication_token
      }, status: :ok
    else
      render json: { error: "Google认证失败" }, status: :unprocessable_entity
    end
  end
end

4. 后续请求携带Token的方式

前端后续请求需在请求头中携带Token,示例:

Authorization: Bearer YOUR_AUTHENTICATION_TOKEN
# 或使用devise配置的键名
access-token: YOUR_AUTHENTICATION_TOKEN

关于Token验证逻辑的疑问

  • 当请求携带你生成的authentication_token时,Rails会内部验证(通过Devise的Token机制匹配数据库中的Token),不会再次调用Google API。
  • 若需更新Google的access_token,需自行实现逻辑:用存储的refresh_token调用Google的Token刷新接口,更新用户记录中的Google access_token。

额外注意事项

  • Rails API模式下默认禁用Cookie中间件,若强制使用Cookie Session(不推荐API场景),需在config/application.rb中添加:
config.middleware.use ActionDispatch::Cookies

同时前端请求需携带credentials: include参数。

内容的提问来源于stack exchange,提问作者jasonwaiting

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:55:10