问题
当前 OAuth 登录成功后,后端把完整 access token 放进回跳前端的 URL fragment:
backend/app/api/v1/oauth.py(oauth_callback):fragment = urlencode({"token": access_token, "expires_at": ...}) → 302 {OAUTH_FRONTEND_REDIRECT_URL}#{fragment}
frontend/src/app/oauth/callback/page.tsx:读取 fragment 中的 token,写 presence cookie / Context 后 history.replaceState 清理。
同响应已通过 _set_auth_cookies 下发 HttpOnly cookie,但 fragment 中的 token 削弱了这一防护收益:token 对前端 JS 可见,且在跳转瞬间存在于浏览器地址栏、history、可能的扩展读取面。虽然 fragment 不进 server log / Referer,这仍是可收窄的凭证暴露面。
建议方向
研究移除 fragment 中的完整 token,仅保留非敏感状态:
- 后端回调只依赖 HttpOnly cookie 建立会话;fragment 仅带
expires_at 等非敏感信息(当前前端已以 /auth/me 校验真实会话,token 读取仅是 presence 标记与兼容路径)。
- 前端回调页改为:不带 token 读取逻辑,直接调用
/auth/me 判定登录态,成功则跳首页,失败显示错误。
- 保留一段兼容观察期(旧 fragment 链接仍能落地但不再消费 token)。
验收标准
关联
问题
当前 OAuth 登录成功后,后端把完整 access token 放进回跳前端的 URL fragment:
backend/app/api/v1/oauth.py(oauth_callback):fragment = urlencode({"token": access_token, "expires_at": ...})→302 {OAUTH_FRONTEND_REDIRECT_URL}#{fragment}frontend/src/app/oauth/callback/page.tsx:读取 fragment 中的 token,写 presence cookie / Context 后history.replaceState清理。同响应已通过
_set_auth_cookies下发 HttpOnly cookie,但 fragment 中的 token 削弱了这一防护收益:token 对前端 JS 可见,且在跳转瞬间存在于浏览器地址栏、history、可能的扩展读取面。虽然 fragment 不进 server log / Referer,这仍是可收窄的凭证暴露面。建议方向
研究移除 fragment 中的完整 token,仅保留非敏感状态:
expires_at等非敏感信息(当前前端已以/auth/me校验真实会话,token 读取仅是 presence 标记与兼容路径)。/auth/me判定登录态,成功则跳首页,失败显示错误。验收标准
关联