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

基于Rails7、Devise和Doorkeeper的PKCE与OmniAuth回调重定向问题

解决Rails 7 + Devise + Doorkeeper + OmniAuth PKCE流程回调丢失应用信息的问题

核心思路是在PKCE授权流程启动时,将Doorkeeper客户端的关键信息存入Session,待OmniAuth回调完成后,从Session中取出信息完成正确的程序化重定向。

步骤1:修改Doorkeeper授权逻辑,存储客户端信息到Session

在Doorkeeper的resource_owner_authenticator中,检测当前请求是否为Doorkeeper的授权请求,若为PKCE流程,则将客户端的client_id和redirect_uri存入Session:

resource_owner_authenticator do
  # 捕获Doorkeeper客户端实例,存入Session供后续回调使用
  if request.env['doorkeeper.client']
    session[:doorkeeper_client] = {
      client_id: request.env['doorkeeper.client'].id,
      redirect_uri: request.env['doorkeeper.client'].redirect_uri,
      # 可选:存储PKCE相关参数,确保流程完整性
      code_challenge: request.env['doorkeeper.params']['code_challenge'],
      code_challenge_method: request.env['doorkeeper.params']['code_challenge_method'],
      scope: request.env['doorkeeper.params']['scope']
    }
  end

  current_user || warden.authenticate!(scope: :user)
end

步骤2:在OmniAuth回调中读取Session,完成PKCE流程收尾

在OmniAuth成功回调方法中,取出Session中存储的客户端信息,手动生成Doorkeeper授权码并重定向回发起PKCE的应用:

def omniauth_successful_callback
  user = User.find_with_omniauth(request.env['omniauth.auth'])
  sign_in(user, scope: :user) # 确保用户已完成登录

  # 取出并清除Session中的客户端信息(避免重复使用)
  unless (client_data = session.delete(:doorkeeper_client)).nil?
    client = Doorkeeper::Client.find(client_data[:client_id])
    
    # 创建Doorkeeper授权记录,生成符合PKCE要求的授权码
    authorization = Doorkeeper::Authorization.create(
      resource_owner_id: user.id,
      client_id: client.id,
      redirect_uri: client_data[:redirect_uri],
      scopes: client_data[:scope],
      code_challenge: client_data[:code_challenge],
      code_challenge_method: client_data[:code_challenge_method]
    )

    # 重定向回发起PKCE的应用,携带授权码
    redirect_to Doorkeeper::Authorization.redirect_uri(client_data[:redirect_uri], authorization)
  else
    # 非PKCE流程的常规登录重定向
    redirect_to root_path
  end
end

额外注意事项

  • 确保Session跨OmniAuth请求可用:检查Devise的session_store配置,避免Session在第三方OAuth跳转后丢失。
  • 依赖Doorkeeper内置验证:Doorkeeper会自动校验redirect_uri是否在客户端允许的列表中,无需额外手动验证。
  • 添加错误处理:可针对客户端不存在、授权记录创建失败等情况添加异常捕获,避免500错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:42:53