Console redirects to sign-in during concurrent session refresh

未关闭
#42,535 3 条评论 1 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
5/5
预计耗时
一周以上
新手友好度
45/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
活跃

调研方向

Read hydration-boundary.tsx, web/app/auth/refresh/route.ts, web/service/refresh-token.ts, account_login_service.py, and account_login_adapters.py to trace concurrent refresh handling. Reproduce overlapping refresh requests and inspect navigation plus refresh responses. Done means valid shared sessions converge without unnecessary sign-in redirects, while expired or revoked sessions still recover in a bounded way without loops.

由索引模型根据 Issue 内容生成。

描述

🐞 bug cloud status: deferred web
Self Checks
  • I have read the Contributing Guide and Language Policy.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.
Dify version

1.17.1 on Dify Cloud, observed on September 18, 2026. API and Web image tags were hotfix-1.17.1-fix.0; the API trace's service.version was dify-1.17.1-9f6153c3d55aaa60e0e7e46078da54f9765f9376.

The source paths discussed below were rechecked against main at 5568aa0ea57d3a2c1cec03bd747b975494f094e3 on September 19. The refresh route, client refresh helper, and backend session refresh/rotation files are unchanged between these two revisions. Runtime reproduction was on Cloud, not a build of the latest main.

Cloud or Self Hosted

Cloud

Steps to reproduce

Concurrent Console session refresh can navigate an authenticated browser to /signin, even though a usable session remains available. This report tracks that recovery behavior separately from the login-page cache loop in #38457.

  1. Sign in to https://cloud.dify.ai/ and verify that the Console home page is accessible.
  2. In the same browser profile/context, create a set of eight test tabs so that they share authentication cookies with the signed-in tab.
  3. Dispatch navigation in these eight test tabs concurrently to https://cloud.dify.ai/auth/refresh?redirect_url=%2F (the test used a parallel batch of browser navigation calls).
  4. Inspect navigation history as well as final URLs. A final Home page alone can hide a preceding sign-in redirect.
  5. Correlate this window with complete API access logs for POST /console/api/refresh-token; successful and rejected refresh requests can be absent from sampled traces.

This was a targeted concurrency test in the Codex in-app browser. It deliberately invokes the existing refresh route with a logged-in session; it does not reproduce the full natural access-token-expiry sequence. A preceding two-tab attempt ended at Home in both tabs. The eight-tab attempt also eventually ended at Home, but its history recorded:

2026-09-18T11:30:01.343Z
Sign in - Dify
https://cloud.dify.ai/signin?redirect_url=%2F

The issue is timing-dependent; one observed eight-tab run is not a measured reproduction rate. No cookies were manually deleted, no logout endpoint was invoked, and no application data was changed during this test.

✔️ Expected Behavior

Concurrent refresh attempts for a shared browser session should converge on a usable renewed session without unnecessarily navigating an already-authenticated user to sign-in.

A regression test should cover overlapping refresh-route requests, browser API refresh overlapping with server-side refresh, and out-of-order responses. Genuinely expired or revoked sessions should still require authentication, with bounded recovery and no redirect loop.

❌ Actual Behavior

At least one navigation passed through /signin during the concurrent test before all test tabs returned to Home. This demonstrates an unnecessary authentication redirect; it does not by itself demonstrate permanent session revocation.

Additional production evidence

The investigation began with a user reporting unexpected logout. The associated Console request sequence included:

2026-09-18 09:57:41.398 UTC  GET  /console/api/explore/apps  401  (server span)
2026-09-18 09:57:41.756 UTC  POST /console/api/refresh-token 200  (access log)
2026-09-18 09:57:42.791 UTC  GET  /console/api/explore/apps  200  (access log)

The account associated with the successful retry subsequently had 35 authenticated API requests returning 200 through 09:59:14 UTC. Separately, complete access logs contain a server-side refresh from a Web pod returning 401 at 09:57:46.149 UTC; it has no corresponding sampled trace. That internal request lacks a session correlation identifier, so it cannot be conclusively attributed to the original user.

Refresh 200s and 401s were also present in the concurrent browser test window. Those log queries covered shared production traffic: exact per-test success/failure counts are not claimed without a unique correlation key. Private account identifiers, cookie values, internal addresses, and observability links are omitted.

Relevant implementation and candidate mechanism

This is a source-supported candidate explanation for the observed redirect, not a claim that every request in the original incident used the same refresh token. The full original logout and its precise interleaving still need request-level correlation. Simply serializing rotation may still reject callers already carrying a superseded token; recovery semantics need to handle that case without weakening revocation.

Related work

  • #38457 and draft PR #38458 cover the sign-in profile-cache redirect loop. The PR changes the login-page probe, not backend refresh rotation or server/client refresh coordination.
  • #30827 / merged PR #30828 address a browser refresh-lock deadlock.
  • PR #41914 proposes dead-token/sign-in-loop handling, but was closed without merging and does not address backend rotation.

From Codex

主要语言
TypeScript
星标
157k
派生
24.7k
平均合并
22 小时 32 分钟
30 天内合并 PR
611

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

langgenius/dify 的其他 Issue

查看 langgenius/dify 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。