跳转到内容

RP 密钥配置与轮换

查看 Markdown

RP 密钥用于在 /token 证明客户端身份,并验证客户端的签名 Request Object。它与签发 ID Token 的提供方密钥、签发 access token 的应用密钥分别配置。见令牌验证。

来源 配置内容 RP 保存的内容
平台 client-auth 密钥 为托管客户端选择平台密钥来源。 创建或轮换时提供的 client-auth 私钥。
内联 RP JWKS 注册包含 RSA 签名公钥的 JSON jwks 对象。 对应私钥。
RP JWKS URI 注册提供公钥 JWKS 的 HTTPS jwks_uri。 对应私钥,并维护 HTTPS 端点。

验证只使用所选来源。RP 密钥查找或签名验证失败时,不会改用平台 client-auth 密钥。动态注册使用 private_key_jwt 时,必须提供 jwks 或 jwks_uri 中的一项。

动态注册的客户端可在 With 打开应用 OIDC 页面,再通过链接进入组织的 OIDC 客户端管理页面。组织 OWNER 可以在那里选择来源并保存公钥配置。如果编辑期间页面内容已变化,请重新加载当前配置,再保存。

在受保护的后端工作目录中运行以下 Node.js 示例。它创建新的密钥对。如果 rp-private.pem 已存在,示例会失败,避免意外覆盖私钥。

import { generateKeyPairSync } from 'node:crypto';
import { writeFileSync } from 'node:fs';
const { privateKey, publicKey } = generateKeyPairSync('rsa', {
modulusLength: 2048,
});
writeFileSync('rp-private.pem', privateKey.export({
format: 'pem',
type: 'pkcs8',
}), { mode: 0o600, flag: 'wx' });
const jwk = publicKey.export({ format: 'jwk' });
const jwks = { keys: [{
...jwk,
kid: 'rp-signing-1',
alg: 'RS256',
use: 'sig',
key_ops: ['verify'],
}] };
writeFileSync('rp-public-jwks.json', JSON.stringify(jwks, null, 2), {
flag: 'wx',
});

将 rp-public-jwks.json 的内容注册为内联 JWKS,或通过 HTTPS JWKS URI 提供。不要公开 rp-private.pem。

每把公钥必须是至少 2048 位的 RSA 密钥,使用 RS256。d、p、q 等 JWK 私钥字段会被拒绝。JWKS 最多包含 16 把密钥。为每把密钥设置不同的非空 kid,并在签名 JWT 的 header 中携带它。JWT 未提供 kid 时,密钥集合必须只有一把密钥。

使用所选来源对应的私钥签名 RS256 JWT。在 /token 表单中发送标准的 client_assertion_type 和 client_assertion 字段。

Claim 值
iss、sub 你的 client_id。
aud discovery 中完整且精确的 token_endpoint URL。不接受只有 issuer 的值。
iat 当前 epoch 时间,单位秒。保持后端时钟同步。
exp 大于 iat,且最多晚 300 秒。
jti 每次 assertion 使用全新的值,不得重用 assertion。

客户端 assertion 和 Request Object 是不同的 JWT。见令牌兑换和签名请求示例。

计划轮换时,保持密钥来源类型不变:

  1. 生成具有新 kid 的替换密钥。JWKS 中保留当前公钥,并加入新公钥。
  2. 内联 JWKS 在 With 保存合并后的集合。使用 JWKS URI 时,先发布合并集合,再用新密钥签名。提供方缓存远程 RP 公钥最多 60 秒,并限制未知 kid 触发的刷新频率。
  3. 用新私钥签名新的 assertion 和 Request Object,确认请求成功。
  4. 旧密钥签名的请求完成或到期后,移除旧公钥,并保存内联集合或更新 HTTPS 文档。

常规轮换时不要同时更换密钥来源类型。更换来源或编辑密钥可能使正在进行的授权失效;此时重新发起授权。

怀疑私钥泄露时,及时移除对应公钥、更新后端签名,并检查受影响的客户端会话。远程缓存可能在剩余缓存期限内保留旧公钥。如果需要立即停止客户端,请使用应用生命周期控制。

轮换 RP 密钥不会轮换提供方的 ID Token 密钥或应用的 access-token 签名密钥。