Layer 2 — 身份准入规则
身份准入规则控制应用允许哪些身份完成登录。它在用户成功证明身份之后、认证请求被标记为 realized 之前运行。
将它作为独立的一层,是因为“确认用户拥有 [email protected]”与“决定应用是否接受 [email protected]”是两个不同的问题。前者由认证规则处理,后者由身份准入规则处理。
支持的 constraint type
Section titled “支持的 constraint type”身份准入规则支持五种 constraint type,同一应用可以混合使用。层内规则按 OR 组合,任意一条匹配即可放行。
| Type | Payload | 匹配语义 |
|---|---|---|
EMAIL | { "allowedEmails": string[] } | 大小写不敏感的 glob,仅 * 特殊 |
STEAM_ID | { "allowedSteamIds": (string | "*")[] } | 十进制 SteamID64 字符串精确匹配,或字面量 "*" 通配 |
ACCOUNT_ALIAS | { "allowedAccountAliases": string[] } | 对 realize 时账户的账户别名(用户可见、应用不可见、可轮换的句柄)做精确匹配 —— 没有通配 |
SECTOR_SUBJECT | { "allowedSectorSubjects": string[] } | 对 realize 时账户在该应用所属扇区(Sector)下的扇区主体(sector subject)(应用可见的令牌 sub)做精确匹配 —— 没有通配 |
EVERYONE | {} | 无条件放行:匹配每个已通过认证的账户,包括没有任何已验证邮箱的账户。payload 为空。 |
匹配对象都来自当前正在进行准入判定的账户或会话:
EMAIL对应账户持有的所有已验证邮箱,即账户的全部EmailIdentity记录,而不只是本次登录使用的邮箱。只要其中任意一个匹配允许列表即可通过。使用邮箱 OTP 注册时账户尚不存在,此时匹配正在注册的邮箱。STEAM_ID对应两条 Steam 路径验证后得到的 SteamID64 —— 既包括游戏端内通过 Steamworks 的STEAM_TICKETdirect-issue,也包括浏览器端的STEAM_OPENID“Sign in with Steam”。两条路径解析到同一份 Steam 身份。从未关联邮箱的 Steam-first 账户必须依赖STEAM_ID(或ACCOUNT_ALIAS/SECTOR_SUBJECT)规则才能通过;只有EMAIL规则的 Layer 2 会拒绝它们。ACCOUNT_ALIAS对应账户的账户别名 —— 用户在 With 门户中看到并自行管理的、可轮换的句柄(例如quiet-meadow-7h2k-9m4p-3fnp-falcon)。它从不向应用披露,因此适合用来锁定某个具体的人,无论其通过哪个应用 realize。SECTOR_SUBJECT对应账户的扇区主体,即按(账户 × 扇区)生成的不透明标识符,也是应用在令牌中实际收到的sub(例如sub_9SQ5535CRWNDDM2T)。共享同一扇区的应用会为同一用户看到相同值,不同扇区则会看到不同值。它可以用于将应用已经收到的特定用户标识加入允许列表。
ACCOUNT_ALIAS 与 SECTOR_SUBJECT 都是不透明值,只进行精确匹配,不检查格式,也不支持通配。两者都要在账户及其扇区主体存在后才会生成,因此新注册产生的值不可能预先出现在允许列表中。Layer 2 如果只包含这两类规则,就不会接受新注册,只能允许已有账户。两个值都可以轮换;轮换后,引用旧值的允许列表将不再匹配。
EMAIL 通配语义
Section titled “EMAIL 通配语义”allowedEmails 中的每一项以大小写不敏感的方式匹配;只有 * 有特殊含义(匹配零个或多个字符)。其它字符(包括 @、.、+)都是字面量。
| Pattern | 匹配 |
|---|---|
[email protected] | 精确匹配 |
*@example.com | example.com 域下的任意邮箱 |
alice+*@example.com | [email protected] 的任意 plus 变体 |
* | 任意邮箱 |
比较前会对输入做 trim 和 lowercase。
STEAM_ID 语义
Section titled “STEAM_ID 语义”每一项要么是字面量 "*"(匹配任意已验证的 SteamID64),要么是十进制 SteamID64 字符串(大小写敏感精确匹配)。写入时强制 [0-9]{1,20} 的形状。
{ "constraintType": "STEAM_ID", "payload": { "allowedSteamIds": ["76561198000000000", "76561198000000001"] }}ACCOUNT_ALIAS 语义
Section titled “ACCOUNT_ALIAS 语义”每一项是目标账户账户别名的精确字面量 —— 即可轮换、面向用户的句柄(例如 quiet-meadow-7h2k-9m4p-3fnp-falcon)。没有通配,也没有 glob;该值不透明,按字面比对。
{ "constraintType": "ACCOUNT_ALIAS", "payload": { "allowedAccountAliases": [ "quiet-meadow-7h2k-9m4p-3fnp-falcon", "bold-harbor-2x4q-8m1p-5kna-otter" ] }}账户别名是用户在 With 门户中管理的句柄,不会向应用披露。它适合用于允许某位特定用户,而不依赖该用户通过哪个应用登录。用户轮换别名后,引用旧值的允许列表将不再匹配。
SECTOR_SUBJECT 语义
Section titled “SECTOR_SUBJECT 语义”每一项是目标账户在该应用所属扇区下扇区主体的精确字面量 —— 即应用可见的令牌 sub(例如 sub_9SQ5535CRWNDDM2T)。没有通配,也没有 glob;该值不透明,按字面比对。
{ "constraintType": "SECTOR_SUBJECT", "payload": { "allowedSectorSubjects": [ "sub_9SQ5535CRWNDDM2T", "sub_4K2P8M1N7QRWXY3Z" ] }}扇区主体是应用及同一扇区内其他应用实际收到的用户标识符;不同扇区会为同一用户看到不同值。你可以将应用已经用于标识用户的值加入允许列表。用户轮换扇区主体后,引用旧值的规则将不再匹配。
两者都是不支持通配的精确允许列表。如果流程还需要接受新用户注册,请同时配置 EMAIL 或 STEAM_ID 规则。
EVERYONE 语义
Section titled “EVERYONE 语义”EVERYONE 是显式的”本应用对任何人开放”规则。它携带空 payload,无条件匹配每一个已通过鉴权的账户。
{ "constraintType": "EVERYONE", "payload": {}}这不会削弱“允许列表 + 默认拒绝”模型,因为 EVERYONE 本身就是一项显式配置。没有 Layer 2 规则的应用仍会拒绝所有人;EVERYONE 表示任何通过 Layer 1 的账户都可以完成准入。它是唯一能够允许没有已验证邮箱账户的 Layer 2 类型,例如仅通过 Steam 或 Battle.net 登录的用户,因此适合不按身份设限的公开应用。由于层内采用 OR 语义,它与其他规则并列时会匹配所有账户,请谨慎使用。
应用规则结构
Section titled “应用规则结构”每条 Layer 2 规则的外层结构相同,不同类型只有 constraintType 和 payload 的内容不同。
{ "constraintType": "EMAIL", "payload": { "allowedEmails": ["*@example.com"] }, "accessTokenTtlSeconds": null, "refreshTokenTtlSeconds": null}应用上的多条规则之间是 OR:身份匹配任一条规则即可通过。
在 /establish 上收紧
Section titled “在 /establish 上收紧”/establish 中的 realizeConstraints 使用相同结构,用于限制单次认证请求允许的身份:
{ "applicationAnchor": "my-app", "realizeConstraints": [ { "constraintType": "EMAIL", } ]}- 字段缺失 → 不收紧;只看应用规则。
- 字段存在且为空数组 → 拒绝。
- 字段存在且非空 → 与应用规则做 AND。约束内部的 payload 列表本身也必须非空。
应用配置了一条 EMAIL 身份准入规则,内容为 allowedEmails: ["*@example.com"]。管理员入口在一次认证请求中传入 realizeConstraints: [{ constraintType: "EMAIL", payload: { allowedEmails: ["[email protected]"] } }]。
| 用户认证身份 | 应用允许? | Inquiry 允许? | 结果 |
|---|---|---|---|
[email protected] | 是(命中 *@example.com) | 是 | 通过 |
[email protected] | 是(命中 *@example.com) | 否 | 认证后被拒绝 |
[email protected] | 否 | 不适用 | 认证后被拒绝 |
身份准入规则在认证规则之后执行。此时用户已经证明自己拥有该邮箱;身份准入规则只决定应用是否接受这个身份完成当前登录。