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

使用expo-auth-session登出后如何强制重新输入OAuth凭证?

解决方法

问题根源在于:虽然你成功撤销了OAuth Token,但Rails服务端的用户会话(由Devise或其他认证系统维护)仍保存在WebBrowser的Cookie中,导致授权页面自动跳过登录步骤。以下是具体解决步骤:

1. 让Doorkeeper响应prompt=login参数,强制重新认证

你已经在客户端设置了prompt: AuthSession.Prompt.Login,但Doorkeeper默认不会处理该参数,需要自定义授权控制器实现强制登出:

步骤1:创建自定义授权控制器

在app/controllers/doorkeeper/authorizations_controller.rb中添加代码:

module Doorkeeper
  class AuthorizationsController < Doorkeeper::ApplicationController
    def new
      # 当请求包含prompt=login时,清除当前用户会话
      if params[:prompt] == 'login' && respond_to?(:sign_out)
        sign_out current_resource_owner
      end
      super
    end
  end
end

步骤2:配置Doorkeeper使用自定义控制器

修改config/initializers/doorkeeper.rb,添加控制器配置:

Doorkeeper.configure do
  # 保留原有配置,新增以下内容
  controllers do
    authorizations 'doorkeeper/authorizations'
  end
end

2. 确保客户端登录请求的prompt参数正确传递

检查Rails日志中的授权请求,确认prompt=login参数已包含在请求中。如果未正常传递,可直接使用字符串参数:

const [request, response, promptForLogin] = AuthSession.useAuthRequest(
  {
    clientId: "J_OgOWUEjFNOwUrKtq58QEqQ0cPEQv4pqs1kuNtMOyk",
    redirectUri,
    scopes: ["public"],
    prompt: "login", // 直接使用字符串确保参数正确传递
    usePKCE: true,
  },
  {
    revocationEndpoint: "http://localhost:3000/oauth/revoke",
    authorizationEndpoint: "http://localhost:3000/oauth/authorize",
    tokenEndpoint: "http://localhost:3000/oauth/token",
  }
);

3. 可选:登出时主动清除WebBrowser中的服务端会话

如果上述方法无效,可通过WebBrowser打开Rails的登出页面,销毁会话Cookie:

步骤1:配置Rails支持自动登出

修改config/routes.rb,添加GET路由:

devise_scope :user do
  get '/users/logout', to: 'devise/sessions#destroy', as: :logout
end

创建app/views/devise/sessions/destroy.html.erb,自动提交DELETE请求销毁会话:

<!DOCTYPE html>
<html>
<head>
  <script>
    document.addEventListener('DOMContentLoaded', () => {
      const form = document.createElement('form');
      form.method = 'POST';
      form.action = '<%= destroy_user_session_path %>';
      form.innerHTML = `
        <input type="hidden" name="_method" value="DELETE">
        <input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
      `;
      document.body.appendChild(form);
      form.submit();
      setTimeout(() => window.close(), 500);
    });
  </script>
</head>
<body>正在登出...</body>
</html>

步骤2:修改客户端登出方法

const handleLogout = async () => {
  if (token === "") return;

  // 撤销OAuth Token
  await AuthSession.revokeAsync(
    { clientId: "J_OgOWUEjFNOwUrKtq58QEqQ0cPEQv4pqs1kuNtMOyk", token },
    { revocationEndpoint: "http://localhost:3000/oauth/revoke" }
  );

  // 打开登出页面清除会话Cookie
  await AuthSession.startAsync({ authUrl: "http://localhost:3000/users/logout" });
  
  setToken("");
};

内容的提问来源于stack exchange,提问作者João Fernandes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:44:52