Files
social-app/docs/plans/2026-03-10-auth-token-compat-refresh-singleflight.md
T

3.0 KiB

Auth Token Compatibility + Refresh Singleflight Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: 兼容云 Supabase 实际 access token claims(缺失 iss 仍可通过),并修复前端 401 导致 refresh 风暴问题,消除日志中的批量 401/429 警告。

Architecture: 后端保持 HS256 签名校验、exp/sub 必检,将 iss 从“强制存在”改为“存在时校验”;前端在拦截器中加入 refresh 单飞与防重入,避免并发 401 触发多次 refresh 或 refresh 自递归。同步清理无效分支与冗余状态。

Tech Stack: FastAPI, PyJWT, Flutter, Dio, flutter_test


Task 1: 后端 JWT claim 兼容化(无 iss 可通过)

Files:

  • Modify: backend/src/core/auth/jwt_verifier.py
  • Test: backend/tests/unit/core/auth/test_jwt_verifier.py

Step 1: Write failing test

  • 新增用例:token 不含 iss、但 sub/exp 与 HS256 签名合法时应验证成功。

Step 2: Run test to verify it fails

  • Run: cd backend && uv run pytest tests/unit/core/auth/test_jwt_verifier.py -q

Step 3: Write minimal implementation

  • jwt.decoderequire 去掉 iss,仅保留 sub/exp
  • 若 payload 中存在 iss 且配置了 issuer,则手动比对 issuer;不一致时报错。

Step 4: Run test to verify it passes

  • Run: cd backend && uv run pytest tests/unit/core/auth/test_jwt_verifier.py -q

Task 2: 前端 refresh 单飞 + 防递归

Files:

  • Modify: apps/lib/core/api/api_interceptor.dart
  • Test: apps/test/core/api/api_interceptor_test.dart

Step 1: Write failing tests

  • 并发 401 时只调用一次 onTokenRefresh
  • /api/v1/auth/sessions/refresh 自身 401 不触发 refresh 重试。

Step 2: Run tests to verify failures

  • Run: cd apps && flutter test test/core/api/api_interceptor_test.dart

Step 3: Write minimal implementation

  • 增加 _refreshFuture 单飞字段。
  • 非 refresh 请求命中 401 时 await 同一个 refresh future。
  • 对 refresh/logout 认证端点和已重试请求加短路,避免无限重入。

Step 4: Run tests to verify pass

  • Run: cd apps && flutter test test/core/api/api_interceptor_test.dart

Task 3: 清理无效/旧分支并做回归验证

Files:

  • Modify: apps/lib/core/api/api_interceptor.dart(移除无效重试分支)
  • Modify: backend/src/core/auth/jwt_verifier.py(删除不再使用的路径)

Step 1: Refactor cleanup

  • 删除不再可达的分支与重复逻辑,保持行为不变。

Step 2: Full targeted verification

  • Run: cd backend && uv run ruff check src tests
  • Run: cd backend && uv run basedpyright
  • Run: cd backend && uv run pytest tests/unit/core/auth/test_jwt_verifier.py tests/unit/v1/users -q
  • Run: cd apps && flutter test test/core/api/api_interceptor_test.dart test/features/auth

Step 3: Runtime spot-check

  • Run: 登录拿 token 后请求 /api/v1/agent/history,确认不再因缺失 iss 返回 401。