Files
lijiaoqiao/docs/token_auth_middleware_design_v1_2026-03-29.md
Your Name 9e47ba56b7 docs(metrics): sync audit design and gate snapshots
Finalize the audit design notes, record the token auth naming alignment, and refresh the 2026-04-11 gate snapshots against the latest stage validation evidence. The metrics snapshot intentionally keeps M-018 as FAIL because PHASE-07 remains deferred.
2026-04-11 09:35:11 +08:00

153 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 平台鉴权与 Token 校验中间件设计TOK-002
- 版本v1.0
- 日期2026-03-29
- 状态:开发实施设计基线
- 依赖:`docs/token_runtime_minimal_spec_v1.md`
- 目标:实现“仅平台凭证入站”,并为 M-014/M-016/M-021 提供可验证链路。
## 1. 设计目标
1. 所有北向请求必须通过平台凭证校验。
2. 外部 `query key` 入站一律拒绝并记录审计事件。
3. 鉴权结果可追踪到 `request_id + subject_id + token_id`
4. 在不泄露上游凭证的前提下返回标准错误码。
## 2. 适用范围
1. 路由范围:`/api/v1/supply/*``/api/v1/platform/*`
2. 鉴权头:仅支持 `Authorization: Bearer <token>`
3. 排除范围:健康检查、内部探针、公开静态资源。
## 3. 中间件链路
## 3.1 处理顺序
1. `RequestIdMiddleware`
2. `QueryKeyRejectMiddleware`
3. `BearerExtractMiddleware`
4. `TokenVerifyMiddleware`
5. `TokenStatusCheckMiddleware`
6. `ScopeRoleAuthzMiddleware`
7. `AuditEmitMiddleware`
## 3.2 关键规则
1. `QueryKeyRejectMiddleware`
- 拒绝任意 `?key=``?api_key=``?token=` 形式外部参数。
- 返回 `401 QUERY_KEY_NOT_ALLOWED`
2. `BearerExtractMiddleware`
-`Authorization` 直接 `401 AUTH_MISSING_BEARER`
3. `TokenVerifyMiddleware`
- 校验签名、`iss``aud``exp``nbf``jti`
- 签名失败返回 `401 AUTH_INVALID_TOKEN`
4. `TokenStatusCheckMiddleware`
- 查询 token 状态缓存(`active/revoked/expired`)。
- `revoked/expired` 返回 `401 AUTH_TOKEN_INACTIVE`
5. `ScopeRoleAuthzMiddleware`
- 按路由匹配 scope不足返回 `403 AUTH_SCOPE_DENIED`
## 4. 数据与缓存策略
1. 状态源:`platform_token_registry`(运行态主表)。
2. 热缓存:`token_status_cache`TTL 30s
3. 吊销传播:
- 吊销事件写入总线后1~5 秒内刷新缓存。
- 验收阈值:吊销生效延迟 `<= 5s`
## 5. 错误语义
| 场景 | HTTP | error.code | 说明 |
|---|---|---|---|
| 缺失 Bearer | 401 | AUTH_MISSING_BEARER | 请求头缺失 |
| query key 外部入站 | 401 | QUERY_KEY_NOT_ALLOWED | 边界拒绝 |
| token 无效/签名失败 | 401 | AUTH_INVALID_TOKEN | 校验失败 |
| token 已吊销/过期 | 401 | AUTH_TOKEN_INACTIVE | 状态不可用 |
| scope 不足 | 403 | AUTH_SCOPE_DENIED | 权限不足 |
## 6. 审计事件TOK-004 依赖)
1. `token.authn.success`
2. `token.authn.fail`
3. `token.authz.denied`
4. `token.query_key.rejected`
最小字段:
1. `event_id`
2. `request_id`
3. `token_id`(可空,提取失败时为空)
4. `subject_id`(可空)
5. `route`
6. `result_code`
7. `client_ip`
8. `created_at`
## 7. 伪代码(实现参考)
```text
onRequest(req):
reqId = ensureRequestId(req)
if hasExternalQueryKey(req):
emitAudit("token.query_key.rejected", reqId, route, clientIp)
return 401 QUERY_KEY_NOT_ALLOWED
bearer = parseBearer(req.headers.Authorization)
if bearer is null:
emitAudit("token.authn.fail", reqId, route, "AUTH_MISSING_BEARER")
return 401 AUTH_MISSING_BEARER
claims = verifyToken(bearer)
if verify failed:
emitAudit("token.authn.fail", reqId, route, "AUTH_INVALID_TOKEN")
return 401 AUTH_INVALID_TOKEN
status = getTokenStatus(claims.jti)
if status != active:
emitAudit("token.authn.fail", reqId, route, "AUTH_TOKEN_INACTIVE")
return 401 AUTH_TOKEN_INACTIVE
if !checkScopeRole(claims.scope, claims.role, route):
emitAudit("token.authz.denied", reqId, route, "AUTH_SCOPE_DENIED")
return 403 AUTH_SCOPE_DENIED
attachPrincipal(req, claims)
emitAudit("token.authn.success", reqId, route, "OK")
pass
```
## 8. 开发阶段验收(设计级)
1.`TOK-001` 角色、状态机、审计字段一致。
2.`M-014/M-016` 指标定义一致。
3. 与 OpenAPI token 契约草案字段一致。
---
## 9. 变更日志Changelog
### v1.1 - 2026-04-07 P0修复同步
**修复内容**
1. **事件命名与实现对齐**
- supply-api 实现已统一使用 `token.*` 格式TOK-002原生格式
- 映射关系:
- `AUTH-TOKEN-OK``token.authn.success`
- `AUTH-TOKEN-FAIL``token.authn.fail`
- `AUTH-SCOPE-DENY``token.authz.denied`
- `AUTH-QUERY-REJECT``token.query_key.rejected`
2. **M-016 指标口径修正**
- 分母:所有 query key 请求事件(含 `token.query_key``token.query_key.rejected`
- 分子:仅 `token.query_key.rejected` 事件
- 拒绝率 = 分子 / 分母 × 100%
3. **M-014/M-016 边界明确**
- M-014平台凭证入站覆盖率`platform_token` 类型)
- M-016query key 外部拒绝率(所有 query key 请求)
- 两者互不干扰,独立计算
**相关文档**
- `audit_log_enhancement_design_v1_2026-04-02.md` - 审计日志增强设计含P0修复
- `audit_log_enhancement_design_fix_summary_2026-04-02.md` - 修复总结报告