Skip to content

feat(auth): add auth session module with user entity and session management - #147

Closed
xyh202131 wants to merge 1 commit into
1024XEngineer:mainfrom
xyh202131:feat/auth-session
Closed

feat(auth): add auth session module with user entity and session management#147
xyh202131 wants to merge 1 commit into
1024XEngineer:mainfrom
xyh202131:feat/auth-session

Conversation

@xyh202131

Copy link
Copy Markdown
Contributor

变更范围

拆分登录与认证会话模块到独立分支,包含两个子模块:

entities/user —— 用户实体契约

  • index.tsUserAuthTokensUserApis 类型定义(sendCode / register / login / loginByCode / refresh / logout / me / changePassword 共 8 个方法)
  • api.tscreateUserApis 后端适配器,蛇形命名 → 驼峰命名映射,支持注入 ApiClient

features/auth-session —— 认证会话管理

  • index.tsxAuthSessionProvider(三态:booting → guest | authenticated)、useAuthSession() hook、ProtectedRoute 路由守卫(含安全 returnTo 校验)、resolveAuthMode() 开发/生产适配、createLocalUserApis() 本地开发适配器
  • session-storage.ts — refresh token 的 localStorage 持久化与降级处理

模块依赖

测试覆盖(14 个测试用例)

  • StrictMode 下启动 token 旋转只执行一次
  • 登录后 access token 存内存、refresh token 写 localStorage
  • 卸载时自动注销 access token provider
  • 启动恢复失败回退到 guest
  • 注销后 stale 恢复结果不覆盖当前会话
  • stale 启动失败不覆盖更新的登录态
  • 登出先清本地再请求后端
  • 密码修改后清除会话
  • JWT 过期前 60 秒自动刷新
  • 并发 refresh 请求去重
  • resolveAuthMode 开发/生产行为
  • createLocalUserApis 不泄露密码到存储
  • ProtectedRoute 安全 returnTo 校验
  • localStorage 不可用时的降级

…gement

Split the auth session module from the main codebase:

entities/user:
- User, AuthTokens, UserApis type definitions
- createUserApis backend adapter (snake_case -> camelCase mapping)
- Supports ApiClient injection for testability

features/auth-session:
- AuthSessionProvider: three-state session (booting -> guest | authenticated)
- useAuthSession() hook for consuming auth context
- ProtectedRoute: route guard with safe returnTo validation
- resolveAuthMode(): local dev by default, forces backend in production
- createLocalUserApis(): browser-only dev adapter (no password verification)
- session-storage: refresh token localStorage persistence with graceful degradation

Tests: 14 test cases covering session lifecycle, token rotation, StrictMode
dedup, stale request handling, JWT refresh scheduling, local dev adapter,
and route protection.
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
windup Ready Ready Preview Aug 6, 2026 9:47am

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这次改动里有两个高置信问题:当前前端认证契约和仓库里的后端用户服务不一致,另外启动阶段在刷新成功后还会因为后续 me() 失败把可用会话丢掉。

email: string
purpose: 'login' | 'register' | 'reset_password'
}): Promise<void>
register(input: {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里把认证模型定义成了 access/refresh token + code 登录/注册参数,但仓库现有后端 UserService 仍然是 session_token 语义,RegisterInput / LoginByPasswordInput 也不包含 code。按当前代码库状态,这个前端契约不会和后端对得上。

bootstrapGenerationRef.current = bootstrapGeneration
const persistedRefreshToken = loadRefreshToken()
bootstrapPromiseRef.current = persistedRefreshToken
? rotateTokens(persistedRefreshToken).then(async (tokens) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里先成功刷新再调用 apis.me();如果 me() 只是短暂失败,后面的 rejection handler 会把刚刷新的 token 也清掉,导致一个本来可用的会话被当场登出。既然 refresh 返回值已经带了 user,至少不应该因为这一步失败就直接丢会话。

@huyanxius

Copy link
Copy Markdown
Collaborator

这份实现我们评审过,模块划分、注释与测试覆盖都达到了可以进 main 的水准,响应解析的显式校验、refresh 的并发去重、启动期 stale 结果保护都写得对。

考虑到你目前排期紧,这块工作我们接手,内容并入 #158,代码以这份实现为起点复用,PR 正文会注明来源与作者。评审中发现三处需要补齐的地方,已经写进 #158 的实现约束:对业务码 401 的响应式兜底(定时器在标签页挂起时不会准时触发)、跨标签页的 storage 同步(/auth/refresh 轮换 refresh token,两个标签页同时打开会互相失效)、以及 resolveAuthMode 与 AuthModeProvider 的装配职责归还 #103

感谢这份工作,先关掉这个 PR,后续进展在 #158 跟进。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants