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.decode的require去掉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。