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
相关产品推荐
相关产品推荐

