#6624·hoppscotch

[错误]: 自主托管的桌面应用程序登录卡死在旋转图标上 — 设备令牌转移返回 200,但会话从未激活(我的查询仍然为 401)

作者: broscr创建于 2026年8月31日更新于 2026年9月17日
标签bugneed testing

环境

  • Hoppscotch 桌面应用程序: v26.8.0 (通过官方 .deb 安装, hoppscotch 包)
  • Hoppscotch 后端/前端/管理员: v2026.6.0 (自主托管的社区版,使用 Docker 容器)
  • 操作系统: Ubuntu 26.04.1 LTS (amd64)
  • 测试的浏览器: Firefox (官方 Mozilla .deb,非 Snap) 和 Google Chrome (官方 .deb) - 两者都出现了相同的故障,排除了浏览器特定的原因。
  • 部署: hoppscotch/hoppscotch-backend, hoppscotch/hoppscotch-frontend, hoppscotch/hoppscotch-admin, 都为 2026.6.0, 位于 https://selfhost.example.com 后的反向代理中。

描述

通过电子邮件魔术链接流程登录到自主托管实例的桌面应用程序永远不会完成:应用程序在登录屏幕上无限期地显示一个旋转图标,尽管后端在服务器端确认了电子邮件链接,并且令牌在网络层上传递给应用程序的本地循环回环服务器成功。

可重现步骤

  1. 在自定义域后面自主托管 Hoppscotch 后端/前端/管理员 2026.6.0,其中 WHITELISTED_ORIGINS 包含桌面应用程序的 Tauri 原生地址 (app://<domain_with_underscores>) - 我们的配置中已确认存在且格式正确。
  2. 打开 Hoppscotch 桌面应用程序,将其指向自主托管实例,选择"使用电子邮件登录"。
  3. 应用程序打开系统浏览器,打开登录页面;提交电子邮件,收到魔术链接电子邮件。
  4. 在电子邮件中单击魔术链接 → 浏览器确认"您已登录,现在可以返回到应用程序了"。
  5. 切换回桌面应用程序:它仍然处于登录屏幕上,显示无限循环图标。

预期行为

在步骤 4 之后,桌面应用程序应检测到完成的登录并转换为已登录状态。

实际行为

  • 通过 ss -tlnp 确认桌面应用程序进程具有活动的本地回环监听器,例如 127.0.0.1:15000。
  • 通过浏览器开发者工具网络选项卡确认浏览器页面发出的请求: GET http://localhost:<port>/device-token?access_token=<jwt>&refresh_token=<jwt> → 状态 200 OK,响应体为空,没有 CORS 错误,没有红色控制台错误。
  • 尽管响应为 200,应用程序自己的随后的 GraphQL me 查询(通过应用程序自己的 DevTools 捕获)仍然返回:
    {
      "errors": [{
        "message": "Unauthorized",
        "extensions": {
          "code": "UNAUTHENTICATED",
          "stacktrace": [
            "UnauthorizedException: Unauthorized",
            "    at GqlAuthGuard.handleRequest (.../node_modules/@nestjs/passport/dist/auth.guard.js:60:30)",
            "    ...",
            "    at JwtStrategy.authenticate (.../node_modules/passport-jwt/lib/strategy.js:96:21)"
          ]
        },
        "originalError": { "message": "Unauthorized", "statusCode": 401 }
      }],
      "data": null
    }
    
  • 在应用程序的本地持久化日志中检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时的时间: 2026-06-01 10:00:00.000 [DEBUG] [15000] [main] [auth.guard] JwtStrategy.authenticate: UnauthorizedException: Unauthorized
  • 通过应用程序的本地持久化日志检查在查询完成时

内容来源: hoppscotch/hoppscotch