Search K
SCIM 预配
SnapOtter 实现了 SCIM 2.0(System for Cross-domain Identity Management,跨域身份管理系统),用于自动化的用户和组预配。你的身份提供商可以自动创建、更新、停用和重新激活用户账户,并同步组成员关系。
企业版功能
SCIM 预配需要带有 scim 功能的 enterprise 许可证。它在 team 计划中不可用。若没有该功能,所有 SCIM 端点(除发现端点外)都返回 403。
先决条件
- 一个可通过公网 URL 访问的正在运行的 SnapOtter 实例
- 一个带有
scim功能的 enterprise 许可证密钥 - SnapOtter 的管理员访问权限(生成或吊销 SCIM 令牌需要
users:manage权限) - 你的身份提供商的预配设置的管理员访问权限
快速开始
- 生成一个 SCIM bearer 令牌:
bash
curl -X POST https://photos.example.com/api/v1/enterprise/scim/token \
-H "Cookie: snapotter-session=YOUR_SESSION" \
-H "Content-Type: application/json"响应中包含该令牌。请立即保存;它无法再次获取。
json
{
"token": "a1b2c3d4e5f6...",
"message": "Save this token - it cannot be retrieved again"
}- 在你的身份提供商中,配置 SCIM 预配,设置:
- Base URL:
https://photos.example.com/api/v1/scim/v2 - Authentication:Bearer token(粘贴步骤 1 中的令牌)
- Base URL:
身份验证
SCIM 端点使用专用的 Bearer 令牌,与用户会话和 API 密钥分开。
生成令牌
POST /api/v1/enterprise/scim/token 会生成一个新的 SCIM 令牌。此端点需要一个具有 users:manage 权限的有效会话。
令牌以明文形式仅返回一次。SnapOtter 只存储 scrypt 哈希值。如果你丢失了令牌,请吊销它并生成一个新的。
同一时间只有一个 SCIM 令牌处于活动状态。生成新令牌会替换先前的令牌。
吊销令牌
DELETE /api/v1/enterprise/scim/token 会吊销当前的 SCIM 令牌。此端点同样需要 users:manage。
速率限制
SCIM 端点按每个令牌每分钟 1000 个请求进行速率限制。超过此限制会返回 HTTP 429。
支持的资源
| SCIM 资源 | SnapOtter 概念 | 创建 | 读取 | 更新 | 删除 |
|---|---|---|---|---|---|
| User | 用户账户 | 是 | 是 | 是 | 软删除 |
| Group | 团队 | 是 | 是 | 是 | 是 |
WARNING
SCIM Group 映射到 SnapOtter 团队,而非角色。SCIM 无法设置用户的角色。所有通过 SCIM 创建的用户都会被分配 user 角色。要更改用户的角色,请使用 SnapOtter 管理界面。
用户操作
创建用户
POST /api/v1/scim/v2/Users
创建一个新的用户账户,其 authProvider 设置为 scim,角色为 user。该用户会被分配到 Default 团队。如果 active 为 false,则角色改为设置为 disabled。
必需属性:userName。可选属性:externalId、emails、active(默认为 true)。
列出和筛选用户
GET /api/v1/scim/v2/Users
返回分页的用户列表。支持 startIndex 和 count 查询参数(每页最多 200 条结果)。
筛选仅支持 eq(等于),可用于以下属性:
userName eq "jane"externalId eq "ext-12345"
其他筛选运算符和属性会返回 HTTP 400。
获取用户
GET /api/v1/scim/v2/Users/:id
通过 SnapOtter 用户 ID 返回单个用户。
替换用户
PUT /api/v1/scim/v2/Users/:id
替换用户的属性。支持 userName、externalId、emails 和 active。用户名更改会检查冲突(如果新用户名已被另一用户占用,则返回 409)。
修补用户
PATCH /api/v1/scim/v2/Users/:id
使用 SCIM PatchOp 进行部分更新。支持的操作:
| 操作 | 路径 |
|---|---|
replace | active、userName、externalId、emails、emails[type eq "work"].value、name.formatted、displayName |
add | 同 replace |
remove | externalId、emails |
name.formatted 和 displayName 路径为兼容性而被接受,但不会产生持久效果(SnapOtter 不单独存储显示名称)。
无值的 replace 操作(即值为不含 path 的对象)也受支持,可用键为 userName、externalId、emails 和 active。
停用用户(软删除)
DELETE /api/v1/scim/v2/Users/:id
SnapOtter 不会通过 SCIM 硬删除用户。DELETE 会执行软停用:
- 用户的角色从其当前值(例如
editor)更改为disabled:editor,同时保留原始角色。 - 用户的密码被清除。
- 所有活动会话被吊销。
- 所有 API 密钥被吊销。
该用户无法再登录或使用任何 API 密钥。其数据(文件、历史记录)会被保留。
重新激活用户
要重新激活先前已停用的用户,请发送带有 active: true 的 PUT 或 PATCH 请求。SnapOtter 会恢复停用前的原始角色(例如 disabled:editor 再次变为 editor)。如果无法确定原始角色,则回退为 user。
示例:通过 PATCH 停用和重新激活
json
// Deactivate
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{ "op": "replace", "path": "active", "value": false }
]
}
// Reactivate
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{ "op": "replace", "path": "active", "value": true }
]
}组操作
SCIM Group 映射到 SnapOtter 团队。创建组会创建一个团队。组成员关系控制用户所属的团队。
创建组
POST /api/v1/scim/v2/Groups
必需:displayName。可选:members({ value: userId } 数组)。
列出和筛选组
GET /api/v1/scim/v2/Groups
筛选仅支持 displayName eq "..."。分页使用 startIndex 和 count(每页最多 200 条结果)。
获取组
GET /api/v1/scim/v2/Groups/:id
替换组
PUT /api/v1/scim/v2/Groups/:id
替换组名称和完整的成员列表。不在新列表中的现有成员会被移至 Default 团队。
修补组
PATCH /api/v1/scim/v2/Groups/:id
支持以下操作:
| 操作 | 路径 | 效果 |
|---|---|---|
add | members | 将用户添加到团队 |
remove | members[value eq "userId"] | 将用户移至 Default 团队 |
replace | displayName | 重命名团队 |
replace | members | 替换所有成员(被移除的成员移至 Default 团队) |
删除组
DELETE /api/v1/scim/v2/Groups/:id
删除团队。被删除团队的所有成员都会被移至 Default 团队。用户不会被停用或删除。
IdP 设置
Okta
- 在 Okta 管理控制台中,打开你的 SnapOtter 应用程序(或创建一个)。
- 转到 Provisioning 选项卡,然后点击 Configure API Integration。
- 勾选 Enable API Integration 并输入:
- Base URL:
https://photos.example.com/api/v1/scim/v2 - API Token:上面生成的 SCIM bearer 令牌
- Base URL:
- 点击 Test API Credentials,然后点击 Save。
- 在 Provisioning > To App 下,启用:
- Create Users
- Update User Attributes
- Deactivate Users
- 在 Push Groups 下,配置要作为 SnapOtter 团队同步的 Okta 组。
Azure AD / Entra ID
- 在 Azure 门户中,转到你的 SnapOtter 企业应用程序。
- 转到 Provisioning,并将 Provisioning Mode 设置为 Automatic。
- 在 Admin Credentials 下,输入:
- Tenant URL:
https://photos.example.com/api/v1/scim/v2 - Secret Token:上面生成的 SCIM bearer 令牌
- Tenant URL:
- 点击 Test Connection,然后点击 Save。
- 在 Mappings 下,配置用户和组的属性映射。默认设置通常有效,但请确认
userName按预期映射到userPrincipalName或mail。 - 将 Provisioning Status 设置为 On 并保存。
Azure 会按固定的同步周期(通常每 40 分钟)预配用户和组。
发现端点
以下三个端点无需身份验证即可访问,用于描述 SCIM 服务器的功能:
| 端点 | 说明 |
|---|---|
GET /api/v1/scim/v2/ServiceProviderConfig | 服务器功能和支持的特性 |
GET /api/v1/scim/v2/Schemas | User 和 Group 模式定义 |
GET /api/v1/scim/v2/ResourceTypes | 可用的资源类型(User、Group) |
ServiceProviderConfig 会公告以下功能:
| 功能 | 是否支持 |
|---|---|
| Patch | 是 |
| Bulk | 否 |
| Filter | 是(最多 200 条结果,仅 eq 运算符) |
| Change password | 否 |
| Sort | 否 |
| ETag | 否 |
限制
- 筛选:仅支持
eq运算符。复杂筛选、and/or运算符、co(包含)和sw(以...开头)均未实现。 - 批量操作:不支持。
- Sort 和 ETag:不支持。
- 角色:SCIM 无法分配 SnapOtter 角色。所有预配的用户都会获得
user角色。 - MAX_USERS:
MAX_USERS环境变量限制不会在 SCIM 用户创建时强制执行。如果你需要限制用户数量,请在你的 IdP 中管理分配。 - 单一令牌:同一时间只能有一个 SCIM 令牌处于活动状态。如果多个 IdP 需要 SCIM 访问权限,它们必须共享该令牌。
- 组即团队:SCIM Group 对应团队,而非角色或权限组。
故障排除
403 "SCIM provisioning requires an enterprise license with the scim feature"
你的许可证不包含 scim 功能,或者未配置许可证。SCIM 需要 enterprise 计划许可证。请确认已设置 SNAPOTTER_LICENSE_KEY 且许可证包含 scim 功能。
401 "Bearer token required"
SCIM 请求未包含 Authorization: Bearer <token> 标头。请检查你的 IdP 的预配配置。
401 "Invalid token"
令牌与存储的哈希值不匹配。如果令牌被吊销并重新生成,就会发生这种情况。请在你的 IdP 的预配设置中更新令牌。
401 "SCIM not configured"
尚未生成任何 SCIM 令牌。请使用 POST /api/v1/enterprise/scim/token 端点创建一个。
409 "User already exists" / "userName already taken"
已存在同名用户名的用户。当 IdP 重试失败的创建操作时,可能会发生这种情况。请在 SnapOtter 管理面板中检查是否有重复的用户名。
429 "SCIM rate limit exceeded"
IdP 发送的请求超过每分钟 1000 个。这通常发生在大型初始同步期间。大多数 IdP 会在速率限制窗口重置后自动重试。如果问题持续存在,请检查你的 IdP 的预配同步间隔。
用户已取消预配但未从界面中移除
SCIM DELETE 是软停用。已停用的用户仍会以禁用状态出现在管理员用户列表中。这是有意为之,以便保留他们的数据。他们的角色显示为 disabled:<original-role>。
