跳转到内容

Layer 1 — 认证规则

查看 Markdown

认证规则控制应用允许使用哪些认证方式。系统会在向用户展示可选方式时(/reason/email)以及每次实际认证尝试中检查这些规则。

方式Payload说明
PASSKEY_USERNAMELESS{}WebAuthn / FIDO2 passkey 的 discoverable-credential / 无用户名(usernameless) 流程。它 gate 在任何邮箱输入之前显示的那个独立「使用 passkey 登录」按钮。两种 passkey 方法登录时用的是用户注册的同一个 passkey —— 区别只在于由哪个按钮唤起。详见下文的 无用户名 passkey
PASSKEY_REASONED{}WebAuthn / FIDO2 passkey 的邮箱优先流程。它 gate 在用户输入邮箱之后提供的 passkey 选项。
EMAIL_VERIFICATION{}向用户邮箱发送一次性验证码。
STEAM_TICKET{ "allowedSteamAppIds": number[] }在 Steam 发行的游戏客户端内由 Steamworks SDK 发起的一次性 Steam ticket 交换,由 native-api POST /direct-issue/steam-ticket 消费。allowedSteamAppIds 把规则收紧到具体的 Steam App ID 列表。端到端用法见 原生客户端
STEAM_OPENID{}浏览器端的 “Sign in with Steam” 按钮,使用 Steam 的 OpenID 2.0 OP。此处解析得到的 Steam 身份与 STEAM_TICKET 共用同一条用户身份行,所以一个用户从游戏端首次登录后可以接着从网页按钮登录(反之亦然)。这条路径不需要 client ID、client secret、Web API key —— 通过 openid.mode=check_authentication 做无密钥验证。
ACCESS_KEY_DIRECT{}一次性的 AccessKey 凭据登录,由 native-api POST /direct-issue/access-key 消费。凭据格式与端到端流程见 原生客户端
GOOGLE_OAUTH{}通过 Google 作为上游 OIDC 提供方登录。Sudomimus 在此扮演 OIDC 接入方角色。Phase 1 的 payload 为空;未来阶段会加入 allowedHostedDomains 以支持 Google Workspace 域名限制。
GITHUB_OAUTH{ "allowedGitHubOrgs": string[] }通过 GitHub 作为上游 OAuth 2.0 提供方登录(没有 id_token;profile 与已验证邮箱列表通过 GitHub REST API 拉取)。allowedGitHubOrgs 是 GitHub Organization login 的精确匹配列表(大小写不敏感);空数组表示不限制组织,非空表示用户必须属于其中至少一个组织。只有匹配规则包含非空允许列表时,才会请求 read:org scope。未配置组织限制时,授权页与 Phase 2 相同,只请求 read:user user:email
DISCORD_OAUTH{}通过 Discord 作为上游 OAuth 2.0 提供方登录(没有 id_token;profile 与邮箱通过 GET /users/@me 拉取)。Scopes 为 identify email。一封邮箱只有当 Discord 同时返回非空 emailverified: true 时才被视为已验证;否则账户会被创建但不会记录已验证邮箱,因此 Layer 2 EMAIL 规则会 fail-closed(这是有意为之,与 Google / GitHub 一致)。未来阶段将加入 allowedDiscordGuilds 用于服务器(guild)限制。
BATTLENET_OAUTH{}通过 Battle.net 作为上游 OIDC-shaped OAuth 提供方登录。Battle.net 的 /userinfo 只返回 subject 和 BattleTag —— 没有邮箱 —— 因此账户会被创建但不记录已验证邮箱,Layer 2 EMAIL 规则对 Battle.net-only 账户 fail-closed(有意为之)。Battle.net 没有 per-application 限制概念,payload 恒为空。
X_OAUTH{}通过 X(原 Twitter)作为上游 OAuth 2.0 提供方登录。X 的 v2 /2/users/me 不提供邮箱,因此与 Battle.net、Steam 一样,账户会被创建但不记录已验证邮箱,Layer 2 EMAIL 规则 fail-closed(有意为之)。payload 为空;无 per-application 限制。
ENTERPRISE_FEDERATION_APPLICATION_MANAGED{ "connectorAnchor": string }通过你自己组织注册为外部连接的 OIDC 身份提供方进行「使用 …… 登录」。connectorAnchor 指向一个归该应用所属组织所有的外部连接;一条规则渲染一个按钮。登录走标准的鉴权与 realize 流水线。详见使用你的 IdP 登录
ENTERPRISE_FEDERATION_DOMAIN_MANAGED{}让应用 opt-in,接受强制 SSO 登录。payload 为空——外部连接在登录时由用户的邮箱域名解析得出(一个由其所有者设置了 SSO_ONLY 登录策略的已验证域名),不在规则里指名。没有这条规则的应用会拒绝被 SSO 管控的用户。详见使用你的 IdP 登录

STEAM_TICKETACCESS_KEY_DIRECT 的端到端用法见 原生客户端;两种企业联合方法见 域名与联合登录 一节。

每条认证规则描述一种认证方式。要允许多种方式,请分别创建多条规则。

{
"method": "PASSKEY_REASONED",
"payload": {},
"accessTokenTtlSeconds": null,
"refreshTokenTtlSeconds": null
}

STEAM_TICKETpayload 包含允许的 App ID 列表:

{
"method": "STEAM_TICKET",
"payload": { "allowedSteamAppIds": [480, 730] },
"accessTokenTtlSeconds": null,
"refreshTokenTtlSeconds": null
}

两个 TTL 字段是可选的;如果提供,它们会参与发放令牌时的 最小值 fold

/establish 中的 authenticationConstraints 使用相同结构,用于限制单次认证请求:

{
"applicationAnchor": "my-app",
"authenticationConstraints": [
{ "method": "PASSKEY_REASONED", "payload": {} }
]
}
  • 字段缺失 → 不收紧;只看应用规则。
  • 字段存在且为空数组 → 拒绝。
  • 字段存在且非空 → 和应用规则做 AND。

某应用配置了两条认证规则:PASSKEY_REASONEDEMAIL_VERIFICATION。管理员入口在一次认证请求中传入 authenticationConstraints: [{ "method": "PASSKEY_REASONED", "payload": {} }]

方式应用允许?Inquiry 允许?结果
PASSKEY_REASONED提供
EMAIL_VERIFICATION隐藏

用户在这次会话里只看得到 passkey 选项,尽管应用本身也是允许邮箱方式的。

passkey 登录拆分成两个相互独立的 Layer-1 方法,而不是一条带 flag 的规则:

  • PASSKEY_REASONED邮箱优先流程:用户先输入邮箱,/reason/email 解析出其账户,然后用注册过的凭据完成挑战。
  • PASSKEY_USERNAMELESSdiscoverable-credential 流程:在认证 UI 顶部、邮箱框之前,显示一个独立的「使用 passkey 登录」按钮。用户点一下,浏览器弹出原生 passkey 选择器,挑一个凭据并完成验证(指纹 / 面部 / PIN),整个过程无需输入邮箱。

「仅无用户名」的应用 —— 即没有任何邮箱框提供 passkey 选项 —— 只需仅允许 PASSKEY_USERNAMELESS 即可表达:

{
"method": "PASSKEY_USERNAMELESS",
"payload": {}
}

要点:

  • 这两个方法是独立的规则,payload 均为空。要邮箱优先入口就配 PASSKEY_REASONED,要独立按钮就配 PASSKEY_USERNAMELESS,两者都要就都配。已不再有 allowUsernameless 这个 flag。
  • 两个方法都解析到同一条共享的 PASSKEY 凭据行,因此通过其中一个流程注册的凭据可被另一个流程使用。
  • 每次 inquiry 的 authenticationConstraints 可以携带 PASSKEY_USERNAMELESS,把单次 inquiry 收紧到只剩 discoverable-credential 按钮(与应用规则做 AND,和其它方法一样)。
  • Discoverable-credential 流程要求 authenticator 设置 User Verified (UV) 标志(指纹 / PIN)。没有用户验证的无用户名登录会被拒绝 —— 因为没有输入的邮箱可以作为第二因素。
  • 这两条规则不影响 passkey 的注册流程:用户仍然通过常规的”邮箱验证后注册 passkey”路径来添加凭据。PASSKEY_USERNAMELESS 只控制登录时是否提供这个独立按钮。