Layer 3 — 返回规则
返回规则控制认证结果如何交付给应用。系统会检查两次:第一次在 /establish 时,检查请求声明的每一种返回方式;第二次在实际执行所选方式时,例如调用 /status-poll 或通过 OIDC /token 兑换。
支持的 return method
Section titled “支持的 return method”| 方式 | payload(由认证请求提供) | 用途 |
|---|---|---|
CALLBACK | { "callbackUrl": "https://..." } | Web 应用 —— 认证完成后浏览器被重定向到应用的某个 URL。 |
STATUS_POLL | {} | 原生客户端轮询 connect POST /status-poll,以获知认证请求何时变为 realized。 |
REVEAL | {} | 面向开发者、CLI 或手动集成。登录完成后,via.sudomimus.com 会一次性展示访问令牌和/或刷新令牌,由用户手动复制;另一端没有接收结果的应用。 |
DIRECT_ISSUE | {} | 为应用启用 native-api 的一次性签发端点,包括 Steam ticket(POST /direct-issue/steam-ticket)和 AccessKey(POST /direct-issue/access-key)。令牌在同一次请求中签发,不经过 /establish 或 /redeem。 |
OIDC | (不在认证请求中声明) | 将应用启用为 OIDC 接入方,通过 oidc.sudomimus.com 使用标准 authorization_code + PKCE 流程。 |
CALLBACK —— 应用规则形状
Section titled “CALLBACK —— 应用规则形状”应用上的 CALLBACK 规则携带的是允许的回调主机名,不是完整 URL。真实的 URL 在每次 /establish 时由应用提供;规则决定的是这个 URL 的 hostname 是否被允许。
{ "returnMethod": "CALLBACK", "payload": { "allowedCallbackDomains": ["client.example.com", "admin.example.com"] }, "accessTokenTtlSeconds": null, "refreshTokenTtlSeconds": null}Hostname 比较是精确、不区分大小写的 —— client.example.com 不会隐式包含 sub.client.example.com。两者都要允许就要分别列出来。
STATUS_POLL —— 应用规则形状
Section titled “STATUS_POLL —— 应用规则形状”STATUS_POLL 规则的 payload 为空;规则存在即表示启用该返回方式。
{ "returnMethod": "STATUS_POLL", "payload": {}, "accessTokenTtlSeconds": null, "refreshTokenTtlSeconds": null}REVEAL —— 应用规则形状
Section titled “REVEAL —— 应用规则形状”REVEAL 规则的 payload 控制登录成功后向用户展示哪些令牌。includeAccessToken 和 includeRefreshToken 至少有一个必须为 true。
{ "returnMethod": "REVEAL", "payload": { "includeAccessToken": true, "includeRefreshToken": true }, "accessTokenTtlSeconds": null, "refreshTokenTtlSeconds": null}认证请求声明 REVEAL 后,Sudomimus 会在准入阶段直接签发令牌并随响应返回,同时将认证请求标记为 redeemed。此后再对同一次登录调用 /redeem,会返回 InquiryAlreadyRedeemed。多条匹配的 REVEAL 规则按 OR 合并:只要任一规则允许访问令牌,结果就包含访问令牌;刷新令牌同理。
与其他 return method 共存
Section titled “与其他 return method 共存”REVEAL 在 via.sudomimus.com 页面上有最高优先级:它会抑制 CALLBACK 的自动跳转,让用户先复制令牌。如果同时声明了 CALLBACK,用户随后会看到一个 “Continue to app” 按钮可以手动跳过去。STATUS_POLL 仍然会按时告诉轮询的客户端 realized,但客户端再调 /redeem 时会失败 —— 因为 REVEAL 已经 redeem 过 inquiry 了。
DIRECT_ISSUE —— 应用规则形状
Section titled “DIRECT_ISSUE —— 应用规则形状”DIRECT_ISSUE 规则的 payload 同样为空。为应用添加该规则,即可启用 native-api 的 Steam ticket 和 AccessKey 一次性签发端点。
{ "returnMethod": "DIRECT_ISSUE", "payload": {}, "accessTokenTtlSeconds": null, "refreshTokenTtlSeconds": null}DIRECT_ISSUE 不出现在 /establish 的 returnMethods 声明里 —— 那些端点根本不经过 /establish。Layer 3 校验仍然会在 native-api 的 handler 内部运行时进行。
OIDC —— 应用规则形状
Section titled “OIDC —— 应用规则形状”OIDC 规则把应用启用为 OpenID Connect 接入方,可通过 oidc.sudomimus.com 接入。Payload 携带标准的 OIDC 客户端配置:
{ "returnMethod": "OIDC", "payload": { "redirectUris": ["https://app.example.com/oidc/callback"], "postLogoutRedirectUris": ["https://app.example.com/"], "allowedScopes": ["openid", "email", "profile", "offline_access"], "tokenEndpointAuthMethod": "private_key_jwt" }, "accessTokenTtlSeconds": null, "refreshTokenTtlSeconds": null}redirectUris—— 完整 URI 精确匹配。RP 在/authorize中传入的redirect_uri必须与列表中某一项逐字节相等。不支持前缀或通配。postLogoutRedirectUris—— 完整 URI 精确匹配,用于/end-session。allowedScopes—— 客户端允许请求的 OIDC scope 集合。openid必须存在;支持email、profile、offline_access。请求列表外的 scope 会在/authorize阶段失败。tokenEndpointAuthMethod—— 取以下之一:"private_key_jwt"(机密客户端,使用 JWT assertion 在/token上做客户端认证)、"client_secret_basic"(机密客户端,在 HTTPAuthorization: Basic头中携带共享密钥)、"client_secret_post"(机密客户端,在/token的表单体中发送共享密钥),或"none"(公开客户端,必须使用 PKCE)。
OIDC 规则不会出现在 /establish 的认证请求中,因为 OIDC 流程使用自己的 /authorize 端点。
完整流程与库集成示例见 OIDC 接入方。
在 /establish 上声明
Section titled “在 /establish 上声明”/establish 中的 returnMethods 同时承担两个作用:声明本次认证请求使用的返回方式,并携带具体的 callbackUrl,因为应用规则无法预先知道该值。
{ "applicationAnchor": "my-app", "returnMethods": [ { "type": "CALLBACK", "payload": { "callbackUrl": "https://client.example.com/auth/return" } }, { "type": "STATUS_POLL", "payload": {} }, { "type": "REVEAL", "payload": {} } ]}DIRECT_ISSUE 与 OIDC 不会在 /establish 上声明 —— 这两种流程都不经过它。
- 字段缺失 → 返回规则不收紧;运行时仍然按应用规则检查。
- 字段存在且为空数组 → 拒绝。
- 字段存在且非空 → 在
/establish阶段每一项都会和应用返回规则校验。CALLBACK时,URL 的 hostname 必须匹配某条CALLBACK规则的allowedCallbackDomains;STATUS_POLL和REVEAL时,应用必须存在一条同种方法的规则。
应用配置了一条返回规则:CALLBACK,allowedCallbackDomains: ["client.example.com"]。
Inquiry 的 callbackUrl | 结果 |
|---|---|
https://client.example.com/return | 通过 |
https://Client.Example.Com/return | 通过(不区分大小写) |
https://sub.client.example.com/return | 拒绝(不隐式包含子域名) |
https://attacker.com/?redirect=client.example.com | 拒绝(hostname 是 attacker.com) |
STATUS_POLL 在 /status-poll 运行时会再次校验:应用是否仍有 STATUS_POLL 规则,并且 inquiry 的收紧(如果有)是否仍然放行它。
为什么只比 hostname(针对 CALLBACK)
Section titled “为什么只比 hostname(针对 CALLBACK)”Sudomimus 只比较 hostname,不检查 path 或查询参数。平台不了解应用自身的 URL 结构,要求维护精确路径允许列表会增加不必要的负担。应用必须在自己的路由层保证回调处理安全;Sudomimus 负责限制浏览器可以返回的来源(origin)。
(OIDC 的 redirectUris 走的是另一套模型 —— OIDC 标准要求完整 URI 精确匹配,且大多数 OIDC 库本身就为每个客户端固定一个 redirect URI。)