跳转到内容

管理会话

查看 Markdown

登录是会话的起点,不是集成的终点。Connect 提供四个端点处理登录之后的会话生命周期:/refresh/introspect/logout/revoke-all。本页是它们的唯一参考。

走 OIDC 流程的用户另请参考 OIDC 指南中的 /end-session —— 它有相关但更窄的用途。

端点鉴权凭据幂等?影响范围
POST /refreshrefresh token 本身否(轮换 refresh token —— 每个令牌只能用一次)单个会话
POST /introspectaccess token 本身只读单个会话
POST /logoutrefresh token 本身是(两次调用都返回 revoked: true单个会话
POST /revoke-allClient-auth JWT(RS256)某账户在调用应用下的所有会话

这四个端点都不需要额外的基础设施 —— 复用你最初集成时就已经有的密钥。

用 refresh token 换取一个新的 access token 和一个新的 refresh token。刷新采用严格轮换OAuth 2.1 BCP §4.14.2):你提交的 refresh token 在同一次调用中被消费并作废,响应里会把它的替代者交给你。请存下新的 refreshToken,并在下一次刷新时使用它。重复提交一个已经用过的 refresh token 会被视为令牌族被攻陷 —— 整个 refresh token 族都会被吊销,用户必须重新认证。例外是对同一个令牌近乎同时的并发刷新(例如两个浏览器标签页同时刷新):它们会收敛到同一个新会话,而不会把用户登出。但在替代令牌已签发之后再复用旧令牌仍会触发失陷,所以无论如何都请始终存储并使用最新轮换出来的令牌。

Terminal window
curl -X POST https://connect-api.sudomimus.com/refresh \
-H "Content-Type: application/json" \
-d '{ "refreshToken": "..." }'

响应:

{
"accessToken": "<JWT>",
"refreshToken": "<轮换后的 JWT>",
"claims": {
"email": { "requirement": "REQUIRED", "state": "GRANTED" },
"firstName": { "requirement": "OPTIONAL", "state": "GRANTED" },
"lastName": { "requirement": "OFF", "state": "UNKNOWN" }
}
}

请持久化轮换后的 refreshToken,替换掉你刚用过的那个 —— 旧的现在已经失效。claims 块与 /redeem 返回的逐条声明视图相同 —— 如何解读见 claims

鉴权:无需 —— 持有 refresh token 即是凭据。

新的 access token 的 TTL 是最初 /redeem(或 /direct-issue/*、OIDC /token)时算出的那一份;refresh 不会重新决议 TTL。

/refresh 的结果不只有成功或令牌被吊销。如果自上次签发令牌后,某条 required 声明不再满足,例如开发者将策略从 optional 改为 required,或用户撤销授权,本次刷新会返回 ClaimConsentRequired,而不会签发缺少该声明的令牌。

补救方式取决于客户端类型,因为 /refresh 自己无法收集同意:

  • 原生客户端(Steam / AccessKey)靠重新跑一次原本的 direct-issue 来补救,它会返回一个 Errand 交接,让用户授予同意。
  • 浏览器应用靠再次引导用户走一次常规交互式登录来补救。

这在实践中很少见 —— 只在策略或授权于会话中途变化时才会发生 —— 但请把你的刷新路径设计成弹出重新认证提示,而不是把每一次刷新失败都当成强制登出。

/introspect —— 这个令牌还有效吗

Section titled “/introspect —— 这个令牌还有效吗”

向 Sudomimus 查询某个 access token 的当前状态。用它实现「跨服务及时撤销会话」—— 例如用户点击「在所有设备退出」后,希望其他标签页或服务能在有限时间内察觉。

Terminal window
curl -X POST https://connect-api.sudomimus.com/introspect \
-H "Content-Type: application/json" \
-d '{ "accessToken": "..." }'

响应:

{
"status": "active",
"recommendedRecheckSeconds": 600
}

status 可取:

  • "active" —— 关联的 refresh token 存在、未被挂起、未过期。
  • "revoked" —— 关联的 refresh token 已被显式挂起(通过 /logout/revoke-all)。
  • "expired" —— 关联的 refresh token 已过期。
  • "not_found" —— 在调用应用下找不到该令牌,或令牌无法解析。

recommendedRecheckSeconds 是 Sudomimus 建议的缓存时长,超过之后再次 introspect。目前总是 600 秒。把 access token 自己的 exp 当作有效期上限;introspect 是用来及时发现撤销的,不是用来替代签名验证。

鉴权:无需 —— access token 本身就是凭据。任何持有该令牌的一方都能问它是否还有效。

本地签名验证负责正确性;introspect 负责新鲜度。一个合理的搭配:

  • 每次请求都本地验证 access token 的签名和 exp(开销很小)。
  • 机会主义地/introspect —— 每 N 分钟一次、放进后台任务,或者在用户可见的状态变化后调用。

不要每次请求都 introspect,否则就失去了使用签名令牌的初衷。

挂起一个 refresh token。其对应的 access token 在 /introspect 上不再被报告为 active,对它的 /refresh 也会失败。

Terminal window
curl -X POST https://connect-api.sudomimus.com/logout \
-H "Content-Type: application/json" \
-d '{ "refreshToken": "..." }'

响应:

{ "revoked": true }
  • revoked: true —— 令牌被挂起(或者本来已经被挂起/过期;重复调用没问题)。
  • revoked: false —— 令牌无效或未找到。

鉴权:无需 —— 持有 refresh token 即可对这个会话登出(RFC 7009 风格)。

/revoke-all —— 吊销账户所有会话

Section titled “/revoke-all —— 吊销账户所有会话”

挂起某账户在调用应用下签发的所有 refresh token。用于账户接管事件响应、「在所有设备登出」,或支持团队发起的会话终止。

账户通过其 扇区主体(sector subject) 标识 —— 即你的应用在令牌上看到的 subject 值(你用来标识用户的那个 sub),而非原始账户 UUID。Sudomimus 会在内部把它反向映射回底层账户。

Terminal window
curl -X POST https://connect-api.sudomimus.com/revoke-all \
-H "Content-Type: application/json" \
-H "Authorization: SudomimusClientJWT $SUDOMIMUS_CLIENT_AUTH_JWT" \
-d '{ "subject": "sub_9SQ5535CRWNDDM2T" }'

响应:

{ "revokedCount": 3 }

revokedCount 是本次调用挂起的 refresh token 数量。已经挂起或已过期的不会被重复计数。

鉴权:和 /establish 一样需要 client-auth JWT。操作范围是隐式的 —— 只触及调用应用下签发给该账户的会话。无法用某应用的 client-auth 密钥撤销另一个应用的会话。

/redeem ──► access (3h) refresh (30d)
│ │
│ │
▼ │
每次请求都用 │
│ │
▼ 过期 │
/refresh ◄──────────────┤ 新 access + 轮换 refresh
│ │
▼ │
│ │
用户点击「登出」 ──► /logout
吊销
/introspect ──► "revoked"

OIDC 风格的 refresh 见 OIDC 接入方 —— Refresh