# Implementation Plan: SSO Token 统一认证 ## Overview 将标注平台从本地 JWT 签发迁移为 SSO 统一 token 认证。按照后端核心组件 → 中间件改造 → 路由改造 → 前端适配 → 清理的顺序实施,确保每一步都可验证。 ## Tasks - [x] 1. 实现 TokenCacheService - [x] 1.1 创建 `backend/services/token_cache_service.py`,实现内存级 token 缓存 - 实现 `CacheEntry` 数据类(user_info + created_at) - 实现 `get(token)` 方法:查询缓存,检查 TTL,过期则删除并返回 None - 实现 `set(token, user_info)` 方法:写入缓存 - 实现 `invalidate(token)` 和 `clear()` 方法 - 支持通过构造函数配置 TTL(默认 300 秒) - _Requirements: 3.1, 3.2, 3.7_ - [ ]* 1.2 编写 TokenCacheService 属性测试 - **Property 1: Cache hit returns cached user info** - **Property 4: Cache entries expire after TTL** - **Validates: Requirements 3.1, 3.2, 3.7** - [x] 2. 改造 OAuthService,新增 SSO token 验证和刷新方法 - [x] 2.1 在 `backend/services/oauth_service.py` 中新增 `verify_sso_token` 方法 - 调用 SSO `/oauth/userinfo` 端点验证 token - 处理 `{"code": 0, "data": {...}}` 包装格式和标准格式 - SSO 不可用时抛出 HTTPException(503) - token 无效时抛出 HTTPException(401) - _Requirements: 3.3, 3.4, 3.5, 3.6_ - [x] 2.2 在 `backend/services/oauth_service.py` 中新增 `refresh_sso_token` 方法 - 向 SSO `/oauth/token` 端点发送 `grant_type=refresh_token` 请求 - 处理包装格式和标准格式的响应 - _Requirements: 4.2, 4.3_ - [ ]* 2.3 编写 OAuthService 新方法的单元测试 - 测试 `verify_sso_token` 成功/失败/SSO 不可用场景 - 测试 `refresh_sso_token` 成功/失败场景 - _Requirements: 3.3, 3.4, 3.5, 3.6, 4.2, 4.3_ - [x] 3. 改造 AuthMiddleware - [x] 3.1 重写 `backend/middleware/auth_middleware.py` 的 `dispatch` 方法 - 改为先查 TokenCacheService 缓存 - 缓存未命中时调用 `OAuthService.verify_sso_token` 验证 - 验证成功后写入缓存并同步用户到本地数据库 - 移除对 JWTService 的依赖 - 更新 PUBLIC_PATHS(移除 auth 端点,添加 oauth/refresh) - 处理 SSO 不可用(503)和 token 无效(401) - _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 3.6_ - [ ]* 3.2 编写 AuthMiddleware 属性测试 - **Property 2: Successful SSO verification populates cache** - **Property 3: Invalid tokens are rejected** - **Validates: Requirements 3.4, 3.5** - [x] 4. Checkpoint - 后端核心组件验证 - Ensure all tests pass, ask the user if questions arise. - [x] 5. 改造 OAuth Router 和移除 Auth Router - [x] 5.1 改造 `backend/routers/oauth.py` 的 callback 端点 - 移除 `JWTService.create_access_token` 和 `JWTService.create_refresh_token` 调用 - 直接返回 SSO 的 access_token 和 refresh_token - 保留用户信息同步逻辑 - _Requirements: 2.1, 5.1, 5.2, 5.3, 5.4_ - [x] 5.2 在 `backend/routers/oauth.py` 中新增 `/api/oauth/refresh` 端点 - 接收 refresh_token,调用 `OAuthService.refresh_sso_token` - 返回新的 access_token 和 refresh_token - _Requirements: 4.2, 4.3_ - [x] 5.3 在 `backend/routers/oauth.py` 中新增 `/api/oauth/me` 端点 - 从 `request.state.user` 获取用户信息(由中间件填充) - 查询本地数据库返回完整用户信息 - _Requirements: 2.2_ - [x] 5.4 移除 `backend/routers/auth.py` 中的 login、register、refresh 端点 - 保留文件但只保留 `/api/auth/me` 端点(重定向到 `/api/oauth/me`)或直接移除整个 router - 从 `backend/main.py` 中移除 auth router 的注册 - _Requirements: 1.1, 1.2, 1.3_ - [ ]* 5.5 编写 User Sync 属性测试 - **Property 5: User sync invariant** - **Validates: Requirements 5.2, 5.3, 5.4** - [x] 6. 配置和清理 - [x] 6.1 更新 `backend/config.py` - 移除 JWT 相关配置(secret_key, algorithm, expire 等) - 新增 `token_cache_ttl` 配置项 - 更新 `config.dev.yaml` 和 `config.prod.yaml` - _Requirements: 7.1, 7.2, 7.3_ - [x] 6.2 移除不再需要的后端文件 - 删除 `backend/services/jwt_service.py` - 精简 `backend/services/auth_service.py`(移除 register_user, login_user, refresh_tokens) - 移除 `backend/schemas/auth.py` 中不再需要的 schema(UserRegister, UserLogin, TokenRefresh, TokenPayload) - _Requirements: 1.1, 2.3_ - [x] 7. 前端适配 - [x] 7.1 更新 `web/apps/lq_label/src/services/api.ts` 中的 token refresh 逻辑 - 将 refresh 端点从 `/api/auth/refresh` 改为 `/api/oauth/refresh` - 更新 request interceptor 中跳过 token 的路径列表 - _Requirements: 4.1, 4.4_ - [x] 7.2 改造 `web/apps/lq_label/src/components/login-form/login-form.tsx` - 移除本地登录表单,页面加载时自动发起 SSO 登录 - 保留加载状态和错误提示 - _Requirements: 6.1, 1.4_ - [x] 7.3 移除注册相关前端代码 - 移除 `register-form` 组件 - 从 `app.tsx` 路由中移除 `/register` 路由 - 从 `auth-service.ts` 中移除 `register` 函数 - _Requirements: 1.1, 1.4_ - [x] 7.4 更新 `web/apps/lq_label/src/services/auth-service.ts` - 移除 `login`、`register`、`refreshToken` 函数 - 更新 `getCurrentUser` 端点为 `/api/oauth/me` - _Requirements: 1.1, 2.2_ - [x] 8. Final checkpoint - 全面验证 - Ensure all tests pass, ask the user if questions arise. ## Notes - Tasks marked with `*` are optional and can be skipped for faster MVP - Each task references specific requirements for traceability - Checkpoints ensure incremental validation - Property tests validate universal correctness properties - Unit tests validate specific examples and edge cases - 前端改动较小,主要是端点 URL 变更和登录页简化 - 数据库无 schema 变更,用户表结构保持不变