SCIM 安全实现
SCIM 直接创建、修改和停用账号,通常还会同步邮箱、电话、部门、经理和组成员等个人信息。它是高权限管理接口,安全要求应高于普通只读业务 API。
TLS 与客户端认证
- 只通过 HTTPS 提供 SCIM,拒绝明文降级;
- 推荐使用 OAuth 2.0 bearer access token,并校验
iss、aud、有效期和 scope; - 企业级高风险场景可结合 mTLS、私网连接或发送方约束 token;
- 每个客户/租户使用独立凭据,支持轮换、吊销和使用审计;
- 禁止长期共享管理员个人 token,也不要把 token 放在 URL。
RFC 7644 允许服务采用标准认证方案,但不会替你定义一套统一 OAuth scope。服务提供方应公开所需授权方式、token endpoint(如有)、scope、受众、有效期和轮换流程。
最小权限
建议区分:
scim.users.read/scim.users.writescim.groups.read/scim.groups.write- schema 与服务配置读取
- Bulk 或高风险删除
scope 只是粗粒度门槛。服务端还必须把凭据绑定到明确租户,并在每次查询、资源读取、PATCH、Group 引用和 Bulk 子操作中施加同一租户条件。
租户不能由请求参数决定
不能因为客户端在 URL、header 或资源属性中提交了某个 tenant ID,就允许它切换租户。租户边界应从已验证的凭据或可信路由映射得出,请求中的租户值只能用于一致性校验。
账号关联与防接管
自动关联现有账号是最危险的环节之一:
- 优先使用已登记的
externalId ↔ id映射; userName、邮箱和员工号的匹配必须限定在同一租户;- 邮箱可变、可复用,不能仅凭相同邮箱跨租户合并;
- 冲突时返回标准 SCIM 错误并要求人工处理,不要静默覆盖;
- 从 JIT 建号迁移到 SCIM 时,先设计一次性的安全认领流程。
服务端分配的 id 不应重用。删除后若相同人员重新入职,应按企业策略明确是恢复旧资源还是创建新资源。
并发与幂等
meta.version 可对应 HTTP ETag。支持版本控制时:
If-Match: W/"a330bc54f0671c9"
客户端用 If-Match 避免旧数据覆盖新变更,服务端在版本不匹配时返回 412 Precondition Failed。创建重试应先按稳定 externalId 或约定唯一键查询,正确处理 409 Conflict,避免网络超时后重复建号。
PATCH 请求按顺序原子执行;某一步失败时不应留下半更新状态。Bulk 则需要逐项处理结果,不能假定整个批次是一个事务。
查询与资源消耗
- 对
count设置服务端上限; - 限制过滤表达式长度、嵌套、逻辑分支和昂贵属性;
- 对无过滤全量扫描、
co/ew等高成本查询设置配额; - 解析标准 filter AST 后参数化查询,禁止拼接 SQL/LDAP;
- 限制 Bulk 操作数、请求体大小、并发和执行时间;
- 按租户和凭据审计速率,错误使用
tooMany等标准scimType。
隐私、日志与响应
password等returned: never属性不得返回或写入普通日志;- 日志记录租户、客户端、操作、资源 ID、结果和请求 ID,敏感属性值应脱敏;
attributes/excludedAttributes不能绕过属性级授权;- 错误不得泄露其他租户用户是否存在;
- 数据驻留、保留、删除和导出应符合客户合同与适用法规;
- 备份、消息队列和失败重试存储也属于个人信息处理范围。
停用闭环
处理 active: false 或删除时,应明确联动:
- 阻止新登录;
- 撤销或缩短现有会话;
- 撤销 refresh token、个人访问令牌、API key 和应用密码;
- 移除组和角色映射;
- 保留必要审计并按策略删除个人数据;
- 对失败的回收操作告警和重试。
只让 SCIM API 返回成功、却没有真正阻止访问,是严重的安全缺陷。服务应提供可验证的最终状态和审计记录。
上线检查表
- [ ] HTTPS,独立且可轮换的租户级凭据
- [ ] access token 校验签发者、受众、有效期和最小 scope
- [ ] 租户边界来自可信凭据,覆盖查询、引用和 Bulk
- [ ] 稳定、安全的账号匹配规则,不按邮箱跨租户合并
- [ ] 支持 ETag/
If-Match或等价并发控制 - [ ] filter、分页、Bulk、请求体、并发和超时有限额
- [ ] 标准 SCIM 错误,不泄露跨租户存在性和内部实现
- [ ] 停用能联动会话、token、密钥、组和角色回收
- [ ] 敏感属性、日志、备份和失败队列符合隐私策略