11 KiB
IAM Service — Scalar 调用顺序指南(v0.1.0)
Authentication(认证方式)
本服务使用 JWT Bearer Token:
- 登录成功后拿到
access_token - 后续请求在 Header 中带:
Authorization: Bearer <access_token>
- 租户上下文:
- 保护接口默认从 Token claim 的
tenant_id推导租户 - 可选兼容
X-Tenant-ID: <uuid>,若同时提供 Header 与 Token,则必须一致,否则返回 403
- 保护接口默认从 Token claim 的
访问令牌(JWT)除 tenant_id/user_id/roles/permissions 外,还包含:
apps:租户已开通应用列表(如["cms","tms"])apps_version:租户 enabled_apps 版本号(用于客户端判断是否需要刷新会话)
OpenAPI/Scalar 可配置参数(环境变量)
为方便本地调试与演示,服务会在生成 OpenAPI 文档时,将部分 Header 参数的示例值按环境变量动态注入(影响 /scalar 展示,不影响服务鉴权逻辑):
IAM_DOCS_DEFAULT_TENANT_ID:默认租户 ID(用于X-Tenant-IDHeader 的 example)- 未设置时默认:
11111111-1111-1111-1111-111111111111 - 可选强制:
IAM_DOCS_REQUIRE_TENANT_ID=1(未设置则启动时直接失败)
- 未设置时默认:
IAM_DOCS_DEFAULT_TOKEN:默认 Token(用于AuthorizationHeader 的 example)- 可填写裸 JWT 或
Bearer <jwt>;裸 JWT 会自动补齐Bearer - 未设置时默认:
Bearer <access_token> - 可选强制:
IAM_DOCS_REQUIRE_TOKEN=1(未设置则启动时直接失败)
- 可填写裸 JWT 或
通用响应结构
成功响应:
{ "code": 0, "message": "Success|Created|Accepted", "data": {}, "trace_id": null }
错误响应(示例):
{ "code": 20006, "message": "Missing authorization header", "details": null, "trace_id": null }
常见错误码(节选):
- 20006:缺少必要 Header(如 Authorization)
- 20003:无权限(403)
- 20005:账号或密码错误
- 30000:请求参数错误(400)
- 30002:资源不存在(404)
- 30003:资源冲突(409)
- 40000:请求过于频繁(429)
- 10001:数据库错误(500)
Step-by-step(可复制流程)
Step -1:数据库初始化 / 迁移(开发/测试/生产)
本服务新增了“租户已开通应用(enabled_apps)”与“平台超级管理员(SuperAdmin)”能力,对应数据库新增表:
appstenant_entitlementstenant_enabled_apps_history
推荐使用版本化迁移脚本初始化与升级:
- 执行迁移:
scripts/db/migrate.sh - 执行校验:
scripts/db/verify.sh - 回滚(按版本):
scripts/db/rollback.sh
本仓库同时保留开发用的一键重建脚本:scripts/db/rebuild_iam_db.sh(会清库重建,不适合生产)。
Step 0:创建租户(可选)
POST /tenants/register
- Tag:
Tenant - Header:无
- 二次验证(可选但建议生产启用):
- 若设置环境变量
IAM_SENSITIVE_ACTION_TOKEN,则必须传 Header:X-Sensitive-Token: <token>,否则返回 403。
- 若设置环境变量
- Body:
{ "name": "Tenant A", "config": { "theme": { "primary": "#1d4ed8" } } }
成功(201)从 data.id 取出租户 ID:
{ "code": 0, "message": "Created", "data": { "id": "<tenant_id>", "name": "Tenant A", "status": "active", "config": {} }, "trace_id": null }
下一步依赖:tenant_id(用于注册/登录时的 X-Tenant-ID)。
Step 0.1:平台超级管理员(可选,但推荐先完成)
数据库已内置平台租户(Platform tenant):
tenant_id = 00000000-0000-0000-0000-000000000001
在平台租户下注册首个用户,将自动获得平台级权限(用于管理各租户 enabled_apps):
POST /auth/register
- Tag:
Auth - Header:
X-Tenant-ID: 00000000-0000-0000-0000-000000000001 - Body:
{ "email": "superadmin@example.com", "password": "securePassword123" }
Step 1:注册用户
POST /auth/register
- Tag:
Auth - 必需 Header:
X-Tenant-ID: <tenant_id> - Body:
{ "email": "user@example.com", "password": "securePassword123" }
成功(201)从 data.id 取出 user_id(后续可用于用户管理接口):
{ "code": 0, "message": "Created", "data": { "id": "<user_id>", "email": "user@example.com" }, "trace_id": null }
Step 2:登录获取访问令牌(Authentication 入口)
POST /auth/login
- Tag:
Auth - 必需 Header:
X-Tenant-ID: <tenant_id> - Body:
{ "email": "user@example.com", "password": "securePassword123" }
成功(200)从 data.access_token 取出访问令牌:
{ "code": 0, "message": "Success", "data": { "access_token": "<jwt>", "refresh_token": "<opaque>", "token_type": "Bearer", "expires_in": 900 }, "trace_id": null }
下一步依赖:access_token。
Step 3:获取当前租户信息(Tenant)
GET /tenants/me
- Tag:
Tenant - 必需 Header:
Authorization: Bearer <access_token> - 可选 Header:
X-Tenant-ID: <tenant_id>(如提供必须与 token tenant_id 一致)
成功(200):
{ "code": 0, "message": "Success", "data": { "id": "<tenant_id>", "name": "Tenant A", "status": "active", "config": {} }, "trace_id": null }
Step 4:查看当前用户权限(Me)
GET /me/permissions
- Tag:
Me - 必需 Header:
Authorization: Bearer <access_token>
成功(200):
{ "code": 0, "message": "Success", "data": ["tenant:read","tenant:write"], "trace_id": null }
下一步依赖:确认具备目标权限(例如 user:read / role:read)。
Step 4.1:平台层设置租户已开通应用(SuperAdmin)
该能力仅允许拥有平台级权限的用户调用:
iam:tenant:enabled_apps:readiam:tenant:enabled_apps:write
4.1.1 查询某租户 enabled_apps
GET /platform/tenants/{tenant_id}/enabled-apps
- Tag:
Tenant - Header:
Authorization: Bearer <access_token>(平台租户下登录得到的 token)
4.1.2 设置某租户 enabled_apps(全量覆盖,幂等)
PUT /platform/tenants/{tenant_id}/enabled-apps
- Tag:
Tenant - Header:
Authorization: Bearer <access_token> - Body:
{ "enabled_apps": ["cms", "tms"], "expected_version": 0 }
说明:
expected_version可选,用于并发控制;不匹配会返回 409。- 登录签发 token 时会自动把
apps/apps_version注入到 JWT,并对permissions按 enabled_apps 过滤。 enabled_apps必须是“应用注册表 apps 表”中存在且status=active的应用 ID;若传入未知/已下线应用(例如dms),接口会返回 400。
enabled_apps 维护建议:
- 新增应用:通过数据库迁移向
apps(id,name,description,status)插入一行(id推荐全小写短标识,如cms/tms)。 - 下线应用:将
apps.status置为非active(例如disabled),之后将无法再被设置进任何租户的 enabled_apps。 - 查询可用应用(示例 SQL):
SELECT id, name, status FROM apps ORDER BY id;
Step 4.2:平台层 App 生命周期管理(SuperAdmin)
用于维护“允许的 App 注册表”,并提供应用上下线(审批 + 生效时间)能力。
权限要求(平台级):
iam:app:readiam:app:writeiam:app:approveiam:app:delete
4.2.1 新增 App
POST /platform/apps
- Tag:
App - Header:
Authorization: Bearer <access_token>(平台租户下登录得到的 token) - Body(示例):
{ "id": "dms", "name": "DMS", "description": "Document Management System", "app_type": "product", "owner": "team-a" }
4.2.2 查询 App 列表(分页/筛选/排序)
GET /platform/apps?page=1&page_size=20&status=active&app_type=product&sort_by=created_at&sort_order=desc
- Tag:
App - Header:
Authorization: Bearer <access_token>
4.2.3 更新 App 基础信息
PATCH /platform/apps/{app_id}
- Tag:
App - Header:
Authorization: Bearer <access_token> - Body(示例):
{ "description": "DMS v2", "owner": "team-b" }
4.2.4 申请 App 上下线(需要审批,可设置生效时间)
POST /platform/apps/{app_id}/status-change-requests
- Tag:
App - Header:
Authorization: Bearer <access_token> - Body(示例:立即禁用):
{ "to_status": "disabled", "reason": "security patch" }
- Body(示例:延迟生效):
{ "to_status": "disabled", "effective_at": "2026-02-01T00:00:00Z", "reason": "maintenance window" }
4.2.5 审批上下线申请单
GET /platform/app-status-change-requests?status=pending&page=1&page_size=20
POST /platform/app-status-change-requests/{request_id}/approve
POST /platform/app-status-change-requests/{request_id}/reject?reason=...
4.2.6 删除 App(软删除)
DELETE /platform/apps/{app_id}
- Tag:
App - Header:
Authorization: Bearer <access_token> - 二次验证(可选但建议生产启用):
- 若设置环境变量
IAM_SENSITIVE_ACTION_TOKEN,则必须同时传 Header:X-Sensitive-Token: <token>,否则返回 403。
- 若设置环境变量
Step 5:列出用户(User)
GET /users?page=1&page_size=20
- Tag:
User - 必需 Header:
Authorization: Bearer <access_token> - 分页规则:
page默认 1,必须 >= 1page_size默认 20,范围 1..=200
成功(200):
{ "code": 0, "message": "Success", "data": [{ "id": "<user_id>", "email": "user@example.com" }], "trace_id": null }
Step 6:列出角色(Role)
GET /roles
- Tag:
Role - 必需 Header:
Authorization: Bearer <access_token>
成功(200):
{ "code": 0, "message": "Success", "data": [{ "id": "<role_id>", "name": "Admin", "description": "..." }], "trace_id": null }
Step 7:用户-角色绑定(User)
用户注册后默认无角色;通常由具备 user:write 的管理员进行角色分配。
7.1 查询用户角色列表(需要 user:read)
GET /users/{id}/roles
- Tag:
User - Header:
Authorization: Bearer <access_token>
7.2 设置用户角色(全量覆盖,幂等;需要 user:write)
PUT /users/{id}/roles
- Tag:
User - Header:
Authorization: Bearer <access_token> - Body:
{ "role_ids": ["<role_id_1>", "<role_id_2>"] }
说明:
role_ids必须全部属于当前租户,否则返回 400。
限流说明(Auth)
/auth/login:约 2 req/s,burst 10(同一 IP)/auth/register:约 1 req/s,burst 5(同一 IP)- 触发后返回:HTTP 429 +
code=40000
密码重置(User)
用户自助重置(需要旧密码):
- POST
/users/me/password/reset - Tag:
User - Header:
Authorization: Bearer <access_token> - Body:
{ "current_password": "oldPassword123", "new_password": "newPassword456" }
租户管理员重置任意用户(生成临时密码):
- POST
/users/{id}/password/reset - Tag:
User - Header:
Authorization: Bearer <access_token> - 权限:需要
user:password:reset:any - 二次验证(可选但建议生产启用):
- 若设置环境变量
IAM_SENSITIVE_ACTION_TOKEN,则必须传 Header:X-Sensitive-Token: <token>,否则返回 403。
- 若设置环境变量