跳转到内容

原生流程

查看 Markdown

Native API 提供三种直接签发方式:Steam 游戏使用 Steam 票据,已签发的密钥对使用 AccessKey,自行持有的 Ed25519 密钥使用 PublicKey。AccessKey 和 PublicKey 均可认证账户、Agent 或 Automation。

凭据 端点
Steam 票据 POST /direct-issue/steam-ticket
AccessKey POST /direct-issue/access-key
PublicKey POST /direct-issue/public-key

配置三层规则和凭据后,由组织 OWNER 激活应用。应用必须为 ACTIVE,且所属组织和扇区可用。所有直接签发方式都要求 DIRECT_ISSUE 返回规则,以及允许该账户的身份准入规则。

认证规则必须允许下表中的准确方法。Native 根据凭据绑定的主体确定方法,调用方不能选择其他主体类型。这些规则的载荷均为空。

主体 AccessKey PublicKey
账户 ACCESS_KEY_DIRECT PUBLIC_KEY_DIRECT
Agent AGENT_ACCESS_KEY_DIRECT AGENT_PUBLIC_KEY_DIRECT
Automation AUTOMATION_ACCESS_KEY_DIRECT AUTOMATION_PUBLIC_KEY_DIRECT

如果机密后端能够签名 /establish,请使用 Connect 浏览器轮询。没有这种后端的公开客户端应使用设备授权。

对于通过 Steam 发行的游戏,Sudomimus 支持一种完全不打开浏览器的静默登录。用户看不到任何登录提示;他们的 Steam 身份会直接换成一个 Sudomimus 会话。

终端窗口
curl -X POST https://native-api.sudomimus.com/direct-issue/steam-ticket \
-H "Content-Type: application/json" \
-d '{
"applicationAnchor": "my-game",
"steamTicketHex": "<来自 Steamworks GetAuthTicketForWebApi 的 hex 编码 ticket>",
"steamAppId": 480
}'

流程:

  1. 游戏调用 Steamworks 的 ISteamUser::GetAuthTicketForWebApi("sudomimus")——不要用 GetAuthSessionTicket,两者是不同类型的 ticket,不能互换。identity 字符串必须是 "sudomimus"(大小写敏感);其他值会被拒绝。
  2. 游戏等待 GetTicketForWebApiResponse_t 回调,再使用该 ticket。
  3. 把 ticket 字节流 hex 编码后作为 steamTicketHex,连同 applicationAnchor 和 steamAppId 一起 POST 到 /direct-issue/steam-ticket。
  4. Sudomimus 向 Steam 校验 ticket,查找或创建账户,然后 —— 在顺利路径上 —— 在同一次请求中返回 { accessToken, refreshToken }。如果应用要求 Steam 账户尚未提供的同意或资料,这一步会改为返回一个带 Errand 交接的 403 —— 见当 direct-issue 需要同意或资料时。
  5. 拿到令牌后,游戏调用 Steamworks.CancelAuthTicket(handle) 收尾。

Steam 账户是身份来源;缺少必需同意或资料时,仍可能需要浏览器 Errand。

应用必须配置:

  • Layer 1:一条 STEAM_TICKET AuthenticationRule,allowedSteamAppIds: number[] 中包含该游戏的 Steam App ID。
  • Layer 2:至少一条能命中的规则——通常是 STEAM_ID,allowedSteamIds: ["*"] 表示放行任何已验证的 Steam 账户,或者给出一组具体的 SteamID64 字符串。
  • Layer 3:一条 DIRECT_ISSUE ReturnRule。

从未绑定过邮箱的「Steam-first」账户必须依赖 STEAM_ID(或 ACCOUNT_ALIAS / SECTOR_SUBJECT)类型的 Layer 2 规则;只有 EMAIL 规则会把它拒掉。

该端点不需要 client-auth JWT——Steam ticket 本身就证明了用户身份以及这个二进制有权与该应用对话。

对应的 Web 流程。 浏览器中的「Sign in with Steam」按钮使用 Layer 1 的 STEAM_OPENID,而不是 STEAM_TICKET。两条路径都会解析为同一个用户级 Steam 身份,因此用户先从游戏登录后,也可以继续使用网页按钮登录,反之亦然,无需合并账户。STEAM_OPENID 的规则结构见认证规则。

适用于没有 Steam ticket、但目标 Sudomimus 账户已经明确的场景——CLI 工具、自定义启动器、无头服务、自动化测试。「证明」是由 Sudomimus 签发的一对凭据(accessKeyIdentifier + accessKeySecret),在开发者门户中生成后通过线下方式交付给运维方。

终端窗口
curl -X POST https://native-api.sudomimus.com/direct-issue/access-key \
-H "Content-Type: application/json" \
-d '{
"applicationAnchor": "my-cli-tool",
"accessKeyIdentifier": "acs_k_<uuidv4>",
"accessKeySecret": "acs_t_<64 位小写 hex>"
}'

两个凭据字符串都带有强制前缀:

  • acs_k_ —— 公开 identifier,后接 UUIDv4。
  • acs_t_ —— 秘密部分,后接 64 位小写 hex。创建操作会返回这段秘密。如果创建结果不确定,可在十分钟内原样重试同一次操作,以恢复原结果;普通密钥读取不会返回秘密。

前缀是规范形式的一部分。它们让两个部分在视觉上可区分,也方便 secret scanner 通过字面子串匹配到误提交的凭据。

应用必须配置:

  • Layer 1:上表中与凭据主体对应的 AccessKey AuthenticationRule(空 payload)。不显式开启则默认拒绝。
  • Layer 2:一条能匹配目标账户的规则——EMAIL、STEAM_ID、ACCOUNT_ALIAS 或 SECTOR_SUBJECT。
  • Layer 3:一条 DIRECT_ISSUE ReturnRule。

AccessKey 凭据无法创建新账户。 凭据绑定在一个已存在的 Sudomimus 账户上;该账户被删除后,所有与之绑定的凭据在登录时都会被拒绝。

在 with.sudomimus.com 的 Programmatic access → Access keys 中管理凭据;操作步骤见管理访问密钥。已吊销或过期的凭据无法登录。如需轮换凭据,请吊销旧凭据并创建新凭据。

该端点也不需要 client-auth JWT——access-key 的密文本身就是凭据。把 client-auth 私钥嵌进发行给运维的 CLI 里,任何人都能反编译出来,因此再叠一层并不带来真正的防御。

在 Programmatic access → Public keys 中注册 Ed25519 公钥,选择账户、Agent 或 Automation 及其应用或扇区适用范围。私钥保留在自己的系统中。

  1. 序列化请求体,例如 {"applicationAnchor":"my-app"}。
  2. 签署 EdDSA JWT:头部 alg 为 EdDSA,typ 为 vnd.sudomimus.public-key-assertion+jwt,kid 为已注册的 pky_... 凭据标识符。
  3. iss 等于 kid,aud 为 sudomimus-native-public-key,iat 为当前时间,exp 最多为 60 秒后;jti 为全新随机 128 位值的 base64url 编码,requestHash 为实际请求体字节的 SHA-256 摘要经 base64url 编码后的值。
  4. 将同一组请求体字节 POST 到 https://native-api.sudomimus.com/direct-issue/public-key,设置 Content-Type: application/json 和 Authorization: SudomimusPublicKeyJWT <assertion>。

每次新请求都必须使用新的断言和 jti。私钥用于认证签发请求,返回的访问令牌仍是 bearer 令牌。请求及错误格式见 Native API 参考。

直接签发端点在一次请求中验证凭据,不能展示同意表单或收集邮箱地址。如果应用要求用户尚未授权的声明(claim),或要求账户缺少的数据,端点会返回带 Errand 的 403。用户在这个短期有效的浏览器补全流程中授予同意或提供缺失数据:

{
"reason": "ClaimConsentRequired",
"claims": {
"email": { "requirement": "REQUIRED", "state": "UNKNOWN" },
"firstName": { "requirement": "OPTIONAL", "state": "UNKNOWN" },
"lastName": { "requirement": "OFF", "state": "UNKNOWN" },
"staticAvatar": { "requirement": "SYNTHETIC_ONLY", "state": "UNKNOWN" },
"animatedAvatar": { "requirement": "OFF", "state": "UNKNOWN" }
},
"errand": {
"errandKey": "ernd_...",
"url": "https://via.sudomimus.com/errand?key=ernd_...",
"expiresAt": "2026-06-10T12:30:00Z"
}
}

reason 是 ClaimConsentRequired 或 RequiredClaimDataMissing。浏览器交接、轮询契约与各类凭据所需的重试证明,以原生声明与 Errand为准。

任一端点的 200 也会带一个 claims 块(形状与 403 里的相同),所以即便成功,你也能看出哪些可选声明被共享了、哪些被保留了。

账户访问令牌的 typ 为 vnd.sudomimus.application-access+jwt。Agent 和 Automation 访问令牌使用 vnd.sudomimus.workload-access+jwt,并包含成对行动主体标识 act.sub。两者的 sub 都标识所属账户在该扇区内的身份。应用必须明确接受对应令牌类型,并自行实施业务权限检查;凭据适用范围不会授予业务权限。

刷新令牌使用 vnd.sudomimus.application-refresh+jwt,不包含账户或行动主体标识。通过 Session UserInfo 获取当前账户资料声明。签名及当前权限检查见令牌与验证。