跳转到内容

OIDC 流程

查看 Markdown

如果应用已经支持 OpenID Connect,或者你希望直接使用现有 OIDC 库,可以将 Sudomimus 作为标准 OIDC 提供方接入。Sudomimus 的 OIDC provider 部署在 oidc.sudomimus.com,支持带 PKCE 的授权码流程。你的应用在该流程中是接入方(Relying Party,RP)。

适用场景:

  • 你的框架或平台原生支持 OIDC(Next-Auth、Spring Security、Keycloak adapter 等),希望直接把 Sudomimus 接入做 IdP。
  • 你要和某个已经只接 OIDC 的伙伴系统对接。
  • 你更熟悉 OIDC 的 client、scope 和 ID token 概念,不希望使用 Connect 协议。

如果你从零开始、只想做最小的自定义集成,Connect 协议 通常更短。

官方 SDK 主要覆盖 Connect、Session、Device、Native 与 token 验证辅助。如果你的 OIDC 应用还需要验证 Sudomimus 应用 access token,或使用 Session 的 introspect 和 logout,请参考 SDK。OIDC refresh token 必须通过提供方的 /token 端点刷新。

OpenID Foundation 的提供方认证档案列出了 Sudomimus 的下列档案。每个档案检验提供方的一类行为。当前部署实际声明的能力,请以下方的 Discovery 文档为准。

档案 检验内容
Basic OP 使用授权码流程登录。
Config OP 通过 Discovery 发布提供方端点和能力。
Implicit OP 通过前端通道返回 ID Token,可同时返回访问令牌。
Hybrid OP 组合授权码与前端通道令牌。
Dynamic OP 动态客户端注册及相关配置。
Form Post OP 通过 HTTP 表单 POST 返回授权响应。测试覆盖 Basic、Implicit 和 Hybrid 流程。
3rd Party-Init OP 提供方经接入方已注册的登录入口发起登录。

Sudomimus 发布标准 OIDC discovery 文档。将库的 issuer 设置为 https://oidc.sudomimus.com 后,客户端库可以自动读取其余配置:

终端窗口
curl https://oidc.sudomimus.com/.well-known/openid-configuration

Sudomimus 不另外发布 OIDC OpenAPI schema。请通过 discovery 获取当前部署的 端点 URL 与已声明能力,通过 OpenID Connect 和 OAuth 标准理解协议语义,并以 本指南确认 Sudomimus 支持的 profile 与平台约束。生成的 OpenAPI 参考用于 Connect、Session、Native 和 Device 产品 API。

discovery 文档声明:

  • response_types_supported:["code", "id_token", "id_token token", "code id_token", "code token", "code id_token token"]。
  • response_modes_supported:["query", "fragment", "form_post"]。Code 默认使用 query;其他模式须显式请求,使用前请核对已部署的 discovery。
  • userinfo_signing_alg_values_supported:["RS256"];由客户端注册配置启用。
  • authorization_response_iss_parameter_supported:true —— 授权回调按照 RFC 9207 标识提供方。
  • grant_types_supported:["authorization_code", "implicit", "refresh_token"]。
  • scopes_supported:["openid", "email", "profile", "offline_access"]。
  • claims_supported 包含 sub、email、email_verified、name、given_name、family_name、picture 和 picture_animated。
  • claim_state_endpoint 指向 Sudomimus 提供方专属的实时 claim 策略与同意状态端点。
  • id_token_signing_alg_values_supported:["RS256"]。
  • code_challenge_methods_supported:["S256"] —— 包含授权码的流程中,公开客户端必须使用 PKCE,机密客户端推荐使用;不支持 plain。
  • token_endpoint_auth_methods_supported:["private_key_jwt", "client_secret_basic", "client_secret_post", "none"]。
  • ui_locales_supported:["en-US", "zh-CN"]。

在 with.sudomimus.com 中,为需要启用 OIDC 的应用完成以下配置:

  1. 添加一条 Layer 3 OIDC 返回规则:

    {
    "returnMethod": "OIDC",
    "payload": {
    "redirectUris": ["https://app.example.com/oidc/callback"],
    "postLogoutRedirectUris": ["https://app.example.com/"],
    "allowedResponseTypes": ["code"],
    "allowedGrantTypes": ["authorization_code", "refresh_token"],
    "applicationType": "web",
    "allowedScopes": ["openid", "email", "profile", "offline_access"],
    "tokenEndpointAuthMethod": "private_key_jwt"
    }
    }
  2. 与其他应用一样配置 Layer 1 和 Layer 2:至少添加一条认证规则(例如 PASSKEY_USERNAMELESS 或 PASSKEY_REASONED)和一条身份准入规则(例如允许特定邮箱的 EMAIL 规则)。OIDC 流程仍使用平台的同一套用户认证挑战。

  3. 选择客户端认证方式:

    • private_key_jwt(推荐用于机密客户端)—— RP 持有私钥,在 /token 上用 JWT assertion 做客户端认证。在应用的 OIDC 页面选择平台提供的 client-auth 密钥,或已注册的 RP 公钥(内联 JWKS 或 HTTPS JWKS URI)。使用对应私钥签名。验证只使用所选密钥来源。
    • client_secret_basic(机密客户端)—— RP 在 /token 的 HTTP Authorization: Basic 头中携带共享密钥。
    • client_secret_post(机密客户端)—— RP 在 /token 的表单体中发送共享密钥(client_id + client_secret 参数)。
    • none —— 仅限公开客户端(SPA、无后端的移动应用)。包含授权码的流程必须使用 PKCE S256。

client_secret_basic 和 client_secret_post 共用同一把应用密钥。请在 With 门户的应用页面生成或轮换它,并妥善保存。

应用的 applicationAnchor 就是你的 client_id。

开始登录前,请配置所选流程需要的规则和凭据,再由组织 OWNER 激活应用。新应用会保持 DRAFT,直到明确执行激活;登录要求应用为 ACTIVE,且所属组织和扇区均可用。

sequenceDiagram
    autonumber

    participant RP as OIDC 接入方
    participant Browser as 用户浏览器
    participant OIDC as OIDC 提供方
    participant Via as via.sudomimus.com

    RP-->>Browser: 跳转到 /authorize<br/>state + nonce + PKCE challenge
    Browser->>OIDC: GET /authorize
    OIDC-->>Browser: 进入托管认证
    Browser->>Via: 完成认证并确认授权
    Via-->>Browser: 返回已注册的 redirect URI<br/>code + state + iss
    Browser-->>RP: 授权回调
    RP->>OIDC: POST /token<br/>code + PKCE verifier + 客户端认证
    OIDC-->>RP: ID token + access token<br/>可选 refresh token
    RP->>OIDC: GET 或 POST /userinfo<br/>Bearer access token
    OIDC-->>RP: 经 scope 与授权筛选的声明

把用户浏览器跳转到 /authorize,附带标准 OIDC 参数:

https://oidc.sudomimus.com/authorize
?client_id=my-app
&redirect_uri=https%3A%2F%2Fapp.example.com%2Foidc%2Fcallback
&response_type=code
&scope=openid%20email%20profile
&ui_locales=zh-CN%20en-US
&state=<csrf-token>
&nonce=<random-nonce>
&code_challenge=<S256-of-verifier>
&code_challenge_method=S256

必填:client_id、redirect_uri、response_type=code、scope(必须包含 openid)。 公开客户端还必须提供 code_challenge 和 code_challenge_method=S256。 机密客户端可以同时省略这两个 PKCE 参数,但仍须在 /token 完成客户端认证。 空值、不完整的参数组合和不支持的 PKCE 方法都会被拒绝。 选填(建议带上):state、nonce。

下方示例仍使用推荐的 PKCE 流程。不使用 PKCE 的机密 OIDC 客户端必须保留 与本次登录事务绑定的 CSRF 和授权码注入防护,包括 RFC 9700 描述的 nonce 校验及额外防护要求。仅有客户端认证不能替代这些保护。

如果应用已知用户偏好的界面语言,可以传入可选的 ui_locales。请按偏好顺序填写以空格分隔的 BCP 47 语言标签。Sudomimus 会采用第一个支持的值(en-US 或 zh-CN);不支持的值会被忽略,不会阻止登录。这个提示只作用于本次登录,用户仍可在页面中切换语言。

建议让 OIDC 客户端库生成 PKCE 参数。每次发起授权都要生成一组新参数,并把 verifier 与待完成的登录状态一起保存到回调完成为止。

如果需要自行生成:

  • code_verifier 长度必须为 43–128 个字符,只能使用英文字母、数字、-、.、_ 和 ~。
  • code_challenge 是 verifier 的 SHA-256 摘要经过无填充 base64url 编码后的结果。S256 challenge 固定为 43 个字符,只能使用英文字母、数字、- 和 _。
  • /authorize 只发送 code_challenge;在 /token 兑换授权码时,发送原始且未经修改的 code_verifier。

不要重复使用 verifier,也不要把文档里的固定示例用于生产环境。Sudomimus 会拒绝格式不正确的参数和不匹配的 verifier/challenge。

一旦授权请求发送了 challenge,兑换时就必须提供匹配的 verifier,机密客户端也不例外。 如果授权时省略了 PKCE,/token 也必须省略 code_verifier;此时提供 verifier 会被拒绝,以防止降级攻击。

多数应用可以省略 prompt 和 max_age。Sudomimus 会检查当前账户、凭据、应用、规则及同意状态,并可能复用同一应用记住的登录。复用后的 auth_time 仍是原始认证时间,不会把较早的认证变成一次全新认证。

参数 行为
省略 prompt 复用符合条件的已记住登录;需要时继续交互式登录。
prompt=login 要求重新认证。
prompt=select_account 要求重新认证,让用户选择账户。
prompt=consent 再次展示同意步骤,即使用户已经保存了声明共享选择。
prompt=none 尝试复用登录,不显示登录界面;无法静默完成时返回交互错误。
max_age=0 要求重新认证。
正数 max_age 只有原始认证距今不超过指定秒数,且当前检查全部通过时,才允许复用。

max_age 必须是非负十进制整数。prompt 可以用空格组合 login、select_account 和 consent;none 必须单独使用。

使用 prompt=none 时,应分别处理以下错误:没有可复用的有效认证时返回 login_required,需要用户同意时返回 consent_required,需要在浏览器补充必需账户资料时返回 interaction_required。用户准备好完成这些步骤后,再发起交互式授权请求。仅有有效的 id_token_hint 不能建立可复用的登录。

只有当应用需要在用户离开或关闭应用后继续刷新令牌时,才请求 offline_access。Sudomimus 会向用户展示一个默认未选中的独立离线会话选项。如果用户拒绝,登录仍会成功,但返回的 scope 不包含 offline_access,也不会签发 refresh token。应用应以返回的 scope 和是否存在 refresh_token 为准。

Sudomimus 会将用户跳转到 via.sudomimus.com,完成 Layer 1 允许的认证方式。认证和身份准入检查成功后,浏览器会携带 code、原始 state 和 iss=https://oidc.sudomimus.com 返回 redirect_uri。

Sudomimus 验证注册回调地址后发生的授权错误,会携带 error、error_description、原始 state 和同一个 iss 返回该回调。OIDC 库必须把 iss 与本次登录保存的 issuer 做精确比较,并在缺失或不一致时于兑换授权码之前拒绝响应。回调地址验证之前的错误则直接以 JSON 返回。请把 server_error 视为暂时性的服务端故障,让用户稍后重试,并且不要缓存协议错误响应。

授权码有效期为 60 秒,且只能兑换一次。重复使用已兑换的授权码时,如果客户端认证、 回调地址和 PKCE 校验均通过,请求会被拒绝,并撤销该授权码产生的原会话及其刷新令牌。 如果兑换响应丢失,应重新开始授权流程,不要重试该授权码。其他登录会话不受影响。

向 /token 提交授权码。按照 OIDC 规范,请求体必须使用 application/x-www-form-urlencoded:

终端窗口
curl -X POST https://oidc.sudomimus.com/token \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "code=$AUTH_CODE" \
--data-urlencode "redirect_uri=https://app.example.com/oidc/callback" \
--data-urlencode "code_verifier=$PKCE_VERIFIER" \
--data-urlencode "client_id=my-app" \
--data-urlencode "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
--data-urlencode "client_assertion=$CLIENT_ASSERTION_JWT"

client_assertion 是使用客户端所选公钥来源对应的私钥签名的 JWT。必需声明包括:iss = client_id、sub = client_id、aud = 完整且精确的 token endpoint URL(生产环境为 https://oidc.sudomimus.com/token)、全新的 jti、iat 和 exp(与 iat 相差不超过 300 秒)。签名算法为 RS256。

成功响应(JSON):

{
"access_token": "<JWT>",
"token_type": "Bearer",
"expires_in": 10800,
"id_token": "<JWT>",
"scope": "openid email profile"
}
  • id_token —— 由 Sudomimus 的平台级 OIDC 密钥签发,通过 https://oidc.sudomimus.com/.well-known/jwks.json 验证。它包含最小协议声明(iss、sub、aud、exp、iat、at_hash,以及可选的 nonce、auth_time)和认证上下文(amr、acr)。个人资料从 /userinfo 获取。
  • access_token —— 由应用的 token-signing 密钥签发,结构与 Connect 协议的访问令牌相同。
  • refresh_token —— 仅在请求了 offline_access 且用户允许离线会话时返回。

默认返回 JSON。将 OIDC ReturnRule 的 userinfoSignedResponseAlg 设置为 "RS256" 后,接口返回 application/jwt。请使用平台 JWKS 验证签名,并核对 issuer、client_id audience、subject 和有效期。签名响应包含相同的授权资料,不含 nonce 或令牌哈希,有效期不超过提交的 access token 或会话。退役的平台公钥应保留至 ID Token 和签名 UserInfo 均已过期。

终端窗口
curl https://oidc.sudomimus.com/userinfo \
-H "Authorization: Bearer $ACCESS_TOKEN"

返回 scope 允许的声明:

{
"sub": "<sector subject>",
"email": "<只在授予 'email' scope 时返回>",
"email_verified": true,
"name": "<只在授予 'profile' scope 时返回>",
"given_name": "<只在授予 'profile' scope 时返回>",
"family_name": "<只在授予 'profile' scope 时返回>",
"picture": "<只在授予 'profile' scope 时返回>",
"picture_animated": "<只在授予 'profile' scope 时返回>"
}

sub 是 扇区主体(sector subject) —— 按扇区维度、应用可见的标识符,与 id_token 的 sub 相同。请用它作为用户键。/userinfo 同时支持 GET 与 POST。

两种方法都优先使用 Authorization: Bearer 请求头。POST 也支持在 application/x-www-form-urlencoded 表单中传入一个 access_token。 不要同时通过请求头和表单传 Token,也不要重复表单参数;这些请求、空的表单 Token 以及 URL 查询参数中的 Token 都会返回 400 invalid_request。 JSON 和 GET 请求体不能用于传 Token。两种受支持的传递方式都执行相同的 Token 过期、实时会话和声明共享校验。

picture 与私有 claim picture_animated 遵循扇区头像交付约定;见头像声明与交付。

如果应用需要当前策略与同意状态,请携带同一个 Bearer access token 调用 discovery 中的 claim_state_endpoint。它同时支持 GET 与 POST,并且不会返回资料值:

{
"sub": "<sector subject>",
"claims": {
"email": { "requirement": "OPTIONAL", "state": "GRANTED" },
"given_name": { "requirement": "OPTIONAL", "state": "GRANTED" },
"family_name": { "requirement": "OFF", "state": "UNKNOWN" },
"picture": { "requirement": "OFF", "state": "UNKNOWN" },
"picture_animated": { "requirement": "OFF", "state": "UNKNOWN" }
}
}

只返回 email scope 与 profile scope 覆盖的条目。只有 openid scope 时, claims 是空对象。

每个 id_token 都包含:

声明 含义
amr 标准 Authentication Methods References 值。例如 passkey 是 ["hwk", "user"],邮箱验证码是 ["otp"]。
acr Sudomimus 的认证上下文字符串。例如 urn:sudomimus:acr:passkey 或 urn:sudomimus:acr:email-otp。

如果你的 RP 在敏感操作前需要确认用户刚才用了抗钓鱼方式登录,请检查 acr 是否为 urn:sudomimus:acr:passkey。Google、GitHub、Discord、Battle.net、X、Steam 和企业联合登录这类上游身份源都会映射到 amr: ["pwd"];需要区分具体来源时,请看 acr。

如果请求了 offline_access、用户允许离线会话,并且响应中包含 refresh token,再到 /token 兑换:

终端窗口
curl -X POST https://oidc.sudomimus.com/token \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=refresh_token" \
--data-urlencode "refresh_token=$REFRESH_TOKEN" \
--data-urlencode "client_id=my-app"
# 机密客户端再加 client_assertion

刷新时应继续使用授权码兑换时选择的客户端认证方式。使用 client_secret_basic 时,通过 -u "my-app:$CLIENT_SECRET" 发送凭据,并省略 表单中的 client_id;使用 client_secret_post 时,在表单中同时发送 client_id 和 client_secret。

可以传入 scope,缩小会话当前已授权的范围。缩小对该会话永久生效,后续刷新不能恢复已移除的 scope。移除 offline_access 后不再签发 refresh token;移除 openid 后不再签发 ID Token。scope 集合不一致的并发刷新会被拒绝。刷新得到的 ID Token 不包含 nonce。

响应包含 refresh_token 时,用它替换已保存的旧令牌。按顺序执行刷新请求。短暂的轮换宽限期可以处理近乎同时发生的重试,但重试的实际 scope 必须与已完成的轮换一致。宽限期外重用旧令牌可能撤销会话。

https://oidc.sudomimus.com/end-session
?id_token_hint=<id_token>
&client_id=my-app
&post_logout_redirect_uri=https%3A%2F%2Fapp.example.com%2F
&state=<可选>

/end-session 通知 OIDC 会话结束,并把用户跳转到 post_logout_redirect_uri(必须与注册过的某个 URI 完全匹配)。如果 id_token_hint 验证通过,并且其中的 aud 与当前 client 匹配,Sudomimus 会推进账户/应用会话权威,并吊销该账户在这个应用下的旧 ApplicationSession。

伪造、无效或已经无法对应到账户的 hint 不会阻止跳转,只是不会触发应用会话吊销。hint 可以是过期的,这样 RP 即使本地会话已经超时,也仍然可以发起一次干净的 logout。

如果你手上有某一个 refresh token,只想吊销这一条会话,请调用 Session API /logout。如果后端需要在不依赖 id_token_hint 的情况下吊销某个账户在应用内的所有会话,请调用 /revoke-all。详见 管理会话。

绝大多数现代 OIDC 库(Node 的 openid-client、Python 的 authlib、Java 的 nimbus-jose-jwt 等)都能从 issuer URL 自动发现,并自动处理 PKCE、JWKS、令牌验证。这个 Node 示例支持 openid-client 6.x(使用 6.8.6 验证),采用注册为 token_endpoint_auth_method: "none" 的公共 PKCE 客户端:

import * as oidc from "openid-client";
const redirectUri = "https://app.example.com/oidc/callback";
const configuration = await oidc.discovery(
new URL("https://oidc.sudomimus.com"),
"my-app",
{
redirect_uris: [redirectUri],
response_types: ["code"],
token_endpoint_auth_method: "none",
},
oidc.None(),
{
execute: [oidc.enableNonRepudiationChecks],
},
);
export const startSignIn = async (savePendingSignIn) => {
const codeVerifier = oidc.randomPKCECodeVerifier();
const codeChallenge = await oidc.calculatePKCECodeChallenge(codeVerifier);
const state = oidc.randomState();
const nonce = oidc.randomNonce();
await savePendingSignIn({
codeVerifier,
state,
nonce,
});
return oidc.buildAuthorizationUrl(configuration, {
redirect_uri: redirectUri,
scope: "openid email profile",
code_challenge: codeChallenge,
code_challenge_method: "S256",
state,
nonce,
});
};
export const finishSignIn = async (
callbackUrl,
consumePendingSignIn,
createServerSideApplicationSession,
) => {
const pendingSignIn = await consumePendingSignIn();
if (pendingSignIn === undefined) {
throw new Error("OIDC sign-in state is missing or expired");
}
const tokens = await oidc.authorizationCodeGrant(
configuration,
callbackUrl,
{
pkceCodeVerifier: pendingSignIn.codeVerifier,
expectedState: pendingSignIn.state,
expectedNonce: pendingSignIn.nonce,
},
);
const claims = tokens.claims();
if (claims?.sub === undefined) {
throw new Error("The validated ID token did not contain sub");
}
const userinfo = await oidc.fetchUserInfo(
configuration,
tokens.access_token,
claims.sub,
);
await createServerSideApplicationSession({
userKey: claims.sub,
refreshToken: tokens.refresh_token,
});
return userinfo;
};

savePendingSignIn 和 consumePendingSignIn 表示与浏览器本次登录绑定的短期服务端存储。回调时只能消费一次 verifier、state 和 nonce。authorizationCodeGrant 会验证授权响应中的 discovery RFC 9207 issuer 与预期 state,并验证 ID-token nonce;配置的 non-repudiation check 还会通过 discovery 获得的 JWKS 验证 ID-token 签名。全部验证成功后,claims() 才会提供这些 claims。

createServerSideApplicationSession 表示应用自己的会话存储。请使用验证后的、限定于应用的 sub 作为用户键,把 refresh token 留在服务端,并且只向浏览器发送应用自己的 session cookie。不要把返回的 token response 序列化进 cookie。

OIDC ID token 通过 oidc.sudomimus.com/.well-known/jwks.json 上的 JWKS 验证 —— 这是 OIDC 标准机制,OIDC 库会自动做。

但 /token 返回的 access_token 不是使用平台级 OIDC JWKS 验证的令牌。它是结构与 Connect 相同的应用专属访问令牌:payload sub 是配对用户键,sid 是 ApplicationSession,jti 是这个 token 实例。需要按 kid 使用 https://session-api.sudomimus.com/applications/{applicationAnchor}/jwks.json 验证。如果 OIDC 库无法为 access token 配置独立 JWKS,也可以将它视为不透明字符串,只通过 /userinfo 获取声明。详见令牌与验证。

在客户端 allowedResponseTypes 中显式启用 id_token 或 id_token token, 并在 allowedGrantTypes 中允许 implicit。 applicationType="web" 时,所有已注册回调 URI 必须使用 HTTPS,且不能使用 localhost 或回环主机。native 客户端使用已注册的自定义 scheme 或精确的 HTTP 回环 URI,不接受 HTTPS 回调。 请求必须携带非空 nonce,并在验证返回 ID Token 的签名、issuer、audience 和有效期时一并校验。Implicit 默认通过 fragment 返回,也接受 form_post, 不接受 query。PKCE 参数会被忽略;offline_access 在同意流程前移除, 不会返回 refresh token 或授权码。

id_token 仅返回 ID Token,其中包含按 scope、当前策略和授权允许披露的身份声明。 id_token token 还返回 access token、token_type、expires_in 和获准的 scope; 需校验 ID Token 中与 access token 对应的 at_hash。两种响应都包含 iss, 并在请求提供 state 时原样返回。过期后需要重新授权。建议先按上文的 code 流程接入;启用 Implicit 前请确认部署环境的 Discovery 已公布该能力。

显式注册所需的 Hybrid 响应类型,并在 allowedGrantTypes 中同时允许 authorization_code 和 implicit。web 客户端必须使用 HTTPS 回调,且不能使用 localhost 或回环主机。native 客户端遵循上文的 native 回调规则。 Hybrid 默认通过 fragment 返回,也接受 form_post,不接受 query。 所有包含授权码的公开客户端流程都必须使用 PKCE S256;前通道返回 ID Token 时, 请求必须携带 nonce,并由 RP 校验。

  • code id_token 返回授权码和含 c_hash 的 ID Token。随后正常兑换授权码; 获准的 offline_access 仍需用户明确同意。ID Token 使用折叠后的访问令牌 TTL, 不受授权码较短的有效期限制。
  • code token 返回授权码和 AT。兑换不会创建第二个会话,而是在同一个不可刷新的 会话下返回 AT 和 ID Token。
  • code id_token token 还返回含 c_hash 和 at_hash 的 ID Token。 使用前须分别对照实际返回的授权码和 AT 校验这两个哈希。

携带 AT 的 Hybrid 在同意流程前移除 offline_access,不会签发 refresh token。 授权码兑换不会延长会话期限;兑换返回的 ID Token 只包含本次 AT 的 at_hash, 不包含 c_hash。请在各步骤校验 iss、state、签名、audience、有效期、 已提供的 nonce 和对应哈希。通过客户端认证的授权码重放会撤销该码对应的会话, 也会阻止先前 AT 的在线使用。授权失败后应重新发起流程;选择 Hybrid 前请确认 部署环境的 Discovery 已公布该响应类型。

六种响应类型均可请求 response_mode=form_post。已注册回调必须使用 HTTP(S),并接受 application/x-www-form-urlencoded POST 请求体,并在处理凭据前验证 state 和 iss。同时校验 ID Token 的签名、audience、有效期、nonce 以及 适用的 at_hash、c_hash;收到授权码时通过 /token 兑换。

提供方会自动提交 HTML 表单,自动提交不可用时可点击 Continue 按钮。 不要记录该响应或回调请求体。如果 RP 使用 Cookie 关联授权请求,跨站 POST 回调所需 Cookie 应配置 SameSite=None; Secure;显式设置为 SameSite=Lax 或 SameSite=Strict 的 Cookie 不会随该回调发送。

完整请求与响应见动态注册 API;签发与撤销操作见IAT 与 RAT 管理。

使用 Discovery 中的 registration_endpoint。注册必须携带 Initial Access Token(IAT)。

  1. 组织 OWNER 在 With → 组织 → Sector → OIDC 中申请 RP 主机审批。Sudomimus 工作人员批准主机。待审批的申请不授予注册权限。
  2. OWNER 在同一个 Sector OIDC 页面签发 IAT。选择可完成浏览器登录的 ACTIVE 应用模板、到期时间、有限配额、允许的 scope 和流程,并明确授权新客户端启用。
  3. RP 将 IAT 作为 Bearer 凭据发送到 POST /register。

向 POST /register 发送带 Bearer IAT 的 JSON,至少提供 redirect_uris。 默认值为 response_types=["code"]、grant_types=["authorization_code"]、 application_type="web"、pairwise subject、RS256 ID Token 和 token_endpoint_auth_method="client_secret_basic"。使用 private_key_jwt 必须提供 RSA 公钥 jwks 或 HTTPS jwks_uri,私钥留在 RP。不支持的算法和 加密选项会被拒绝。

成功响应为 HTTP 201,返回可用客户端的 client_id、 registration_client_uri 和独立的 Registration Access Token(RAT)。 共享密钥客户端还会收到 client_secret。不要把 IAT、RAT 或客户端密钥放进 浏览器存储、URL 或日志。RAT 可通过 GET registration_client_uri 读取当前 配置和当前共享密钥。它不能编辑注册配置或创建用户会话,但可以通过 DELETE registration_client_uri 删除自己的 OIDC 注册;此操作停用应用,并将其保留为管理资源。读取经过审计, 响应禁止缓存。规则和公钥通过 With 门户修改。 OWNER 可撤销资格、替换 RAT,或撤销整个组织的注册权限。IAT 到期、耗尽或 被撤销,不会自动撤销之前创建的客户端或 RAT。

RP 可以注册可选的 HTTPS initiate_login_uri,该 URI 不能包含片段。它指向 RP 接收第三方发起登录请求的入口,需支持 GET 和 POST。RP 检查 iss 后发起 正常的授权请求。创建响应和 RAT 读取在配置该 URI 时返回它。With 门户只读显示该 URI。 如需为仍有效的动态注册设置、修改或清除它,请联系 Sudomimus 支持团队。

多个回调 host 必须提供 HTTPS sector_identifier_uri,其 JSON 文档包含 每个精确回调 URI。文档 host 必须已获准绑定到组织的 Sector。修改回调时会 重新检查原有绑定及当前文档。Native 客户端可以注册自定义 scheme 或精确 HTTP loopback 地址;启用 Implicit/Hybrid 的 Web 客户端必须使用非 localhost 的 HTTPS 回调。自定义 scheme 不能作为浏览器 Form Post 的提交目标。

客户端名称遵循平台命名策略。提交的法律和首页 URL 作为描述性链接展示。 Logo 仅支持 PNG/JPEG/GIF/WebP,每张不超过 64 KiB;提供方会安全获取图片, 同意页不会从用户浏览器直接请求 RP 的图片服务器。

可运行的示例见OIDC 高级接入与能力,密钥配置见RP 密钥配置与轮换。

Discovery 宣告支持 Request Object 后,已配置 RS256 的客户端可以通过 request 提交签名 JWT,或通过 request_uri 提交 HTTPS 引用。外层必须保留 client_id、response_type 和包含 openid 的 scope。JWT 中的值覆盖其他 外层参数;若包含内层 client/type,必须与外层一致。JWT 可以提供回调 URI。 可选的 iss、aud、exp、nbf、iat 在出现时会被校验。不支持无签名、 加密或嵌套对象。注册的 request_uris 非空时限制可用引用;否则可从允许的 公网 HTTPS 地址获取带有效签名的对象。密钥轮换和注册变更仍会触发实时权限 检查。具体可用能力以部署的 Discovery 为准。