fix(auth): tighten refresh session revocation
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
2. 当前设备识别方式与 `isCurrent` 语义
|
||||
3. 多端登录识别字段如何从 `refresh_session` 派生到 DTO
|
||||
4. Rust 首版在 Axum + 进程内 `module-auth` 下的最小实现边界
|
||||
5. `2026-05-13` 会话组合并展示与远端踢下线闭环修复口径
|
||||
|
||||
## 2. 当前基线
|
||||
|
||||
@@ -46,11 +47,16 @@
|
||||
3. 登录创建 session 时落库结构化客户端身份字段
|
||||
4. 会话列表返回多端识别所需字段,并兼容旧 `clientLabel`
|
||||
|
||||
本阶段明确不包含:
|
||||
`2026-05-13` 起,本接口同时承担账号安全页的会话组读模型:
|
||||
|
||||
1. `/api/auth/sessions/:sessionId/revoke`
|
||||
2. 前端完整消费全部新增字段
|
||||
3. SpacetimeDB reducer / view 正式读表
|
||||
1. 后端按“同设备 + 同 IP”聚合活跃 `refresh_session`
|
||||
2. 前端只消费后端聚合结果,不自行推断合并
|
||||
3. `POST /api/auth/sessions/{sessionId}/revoke` 已纳入 Rust 实现,用于踢下线非当前会话
|
||||
|
||||
本阶段仍明确不包含:
|
||||
|
||||
1. SpacetimeDB reducer / view 正式读表
|
||||
2. 登录方式、refresh token 轮换策略或账号安全页整体重设计
|
||||
|
||||
## 5. 请求与响应 contract
|
||||
|
||||
@@ -70,6 +76,8 @@
|
||||
"sessions": [
|
||||
{
|
||||
"sessionId": "usess_xxx",
|
||||
"sessionIds": ["usess_xxx", "usess_yyy"],
|
||||
"sessionCount": 2,
|
||||
"clientType": "web_browser",
|
||||
"clientRuntime": "chrome",
|
||||
"clientPlatform": "windows",
|
||||
@@ -90,9 +98,12 @@
|
||||
|
||||
字段说明:
|
||||
|
||||
1. `clientLabel` 当前阶段继续兼容旧前端字段,值固定与 `deviceDisplayName` 保持一致
|
||||
2. `clientRuntime`、`clientPlatform`、`deviceDisplayName` 是多端识别首版最小新增字段
|
||||
3. 小程序来源额外暴露 `miniProgramAppId`、`miniProgramEnv`
|
||||
1. `sessionId` 是聚合组代表会话 ID;若组内包含当前 `sid`,代表 ID 必须使用当前会话 ID
|
||||
2. `sessionIds` 是该聚合组内全部活跃 session ID,前端批量踢下线时逐个调用 revoke
|
||||
3. `sessionCount` 是聚合组内 session 数量
|
||||
4. `clientLabel` 当前阶段继续兼容旧前端字段,值固定与 `deviceDisplayName` 保持一致
|
||||
5. `clientRuntime`、`clientPlatform`、`deviceDisplayName` 是多端识别首版最小新增字段
|
||||
6. 小程序来源额外暴露 `miniProgramAppId`、`miniProgramEnv`
|
||||
|
||||
### 5.3 失败响应
|
||||
|
||||
@@ -110,12 +121,25 @@
|
||||
1. 从 refresh cookie 读取当前原始 refresh token
|
||||
2. 在 Axum 侧计算 `sha256(refresh_token)`
|
||||
3. 与会话列表中的 `refresh_token_hash` 比较
|
||||
4. 命中则 `isCurrent = true`
|
||||
4. 同时读取 Bearer access token claims 中的 `sid`
|
||||
5. 聚合组内任意 session 命中当前 refresh hash 或当前 `sid`,则整组 `isCurrent = true`
|
||||
|
||||
说明:
|
||||
|
||||
1. 如果请求没有携带 refresh cookie,本接口仍可返回会话列表
|
||||
2. 此时全部会话的 `isCurrent` 都为 `false`
|
||||
2. 此时仍可通过 Bearer `sid` 标记当前组
|
||||
3. 当前组不允许在前端显示“踢下线”,当前设备退出必须走 `/api/auth/logout`
|
||||
|
||||
## 6.1 会话组合并规则
|
||||
|
||||
同设备同 IP 的 active refresh sessions 在后端合并为一条 DTO:
|
||||
|
||||
1. 优先使用 `device_fingerprint + ip` 作为聚合 key
|
||||
2. 无 `device_fingerprint` 时退化为 `client_type + client_runtime + client_platform + device_display_name + user_agent + ip`
|
||||
3. `createdAt` 取组内最早 `created_at`
|
||||
4. `lastSeenAt` 取组内最新 `last_seen_at`
|
||||
5. `expiresAt` 取组内最新 `expires_at`
|
||||
6. `ipMasked` 仍只返回脱敏 IP
|
||||
|
||||
## 7. 多端标识派生规则
|
||||
|
||||
@@ -161,8 +185,21 @@
|
||||
负责:
|
||||
|
||||
1. 读取 Bearer JWT 与 refresh cookie
|
||||
2. 把活跃会话映射成旧接口兼容 DTO
|
||||
3. 派生 `ipMasked` 与 `isCurrent`
|
||||
2. 按同设备同 IP 聚合活跃会话
|
||||
3. 把活跃会话组映射成旧接口兼容 DTO
|
||||
4. 派生 `ipMasked` 与 `isCurrent`
|
||||
5. 暴露 `POST /api/auth/sessions/{sessionId}/revoke`
|
||||
|
||||
## 8.3 指定会话吊销接口
|
||||
|
||||
`POST /api/auth/sessions/{sessionId}/revoke` 固定规则:
|
||||
|
||||
1. Bearer JWT 必填
|
||||
2. 仅允许吊销当前用户自己的非当前会话
|
||||
3. 当前会话自吊销返回业务错误,提示使用退出登录
|
||||
4. 只撤销目标 `refresh_session`,不递增 `token_version`
|
||||
5. 撤销后同步 auth store 到 SpacetimeDB
|
||||
6. 认证中间件会校验 access token `sid` 对应 active `refresh_session`,因此被踢设备已有 access token 会立即失效
|
||||
|
||||
## 9. 测试策略
|
||||
|
||||
@@ -172,6 +209,9 @@
|
||||
2. 微信内 H5 登录后,会话列表返回 `wechat_h5 + wechat_embedded_browser`
|
||||
3. 显式小程序头优先于 `User-Agent` 判断
|
||||
4. 请求携带当前 refresh cookie 时,只有当前会话 `isCurrent = true`
|
||||
5. 同设备同 IP 会话会合并,并返回 `sessionIds/sessionCount`
|
||||
6. 合并组包含当前 `sid` 或当前 refresh hash 时,整组 `isCurrent = true`
|
||||
7. 指定远端会话吊销后,被踢设备 access token 立即无法通过认证
|
||||
|
||||
## 10. 完成定义
|
||||
|
||||
@@ -181,4 +221,6 @@
|
||||
2. 会话列表可区分普通浏览器、微信内 H5、小程序来源
|
||||
3. 同设备不同浏览器可在会话列表中清晰区分
|
||||
4. `clientLabel` 与新增多端字段都已稳定返回
|
||||
5. 文档、任务清单与测试已同步更新
|
||||
5. 同设备同 IP 的重复 active refresh sessions 已合并展示
|
||||
6. 非当前会话可通过真实 revoke 接口踢下线
|
||||
7. 文档、任务清单与测试已同步更新
|
||||
|
||||
Reference in New Issue
Block a user