You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否缓存Azure AD B2C中用于签署令牌的公钥?是否安全?

关于Azure AD B2C签名密钥缓存的问题解答

核心结论

  • 缓存签名密钥可行且推荐,但不建议存储到环境变量,更适合用内存缓存或专用缓存服务
  • Azure AD B2C的签名密钥会发生变化,必须支持自动刷新机制

密钥变化的场景

Azure AD B2C会在以下情况轮换签名密钥:

  • 定期自动轮换(通常每几个月执行一次)
  • 密钥达到生命周期上限(后台自动过期)
  • 租户管理员手动触发密钥轮换

密钥轮换后,新签发的ID Token会使用新密钥签名,旧密钥会在一段时间内保留,用于验证未过期的旧令牌。

为什么不建议用环境变量存储

环境变量属于静态配置,存在明显缺陷:

  • 密钥更新后,需要手动修改环境变量并重启服务,无法自动适配轮换
  • 无法同时存储多个密钥(轮换期间新旧密钥会共存),可能导致部分令牌验证失败

最佳实践

1. 利用JWKS客户端自带的缓存功能

你使用的jwks-client库本身支持缓存配置,只需初始化时添加参数即可自动处理:

const client = jwksClient({
    jwksUri: discoveryKeysEndpoint,
    cache: true, // 启用缓存
    cacheMaxAge: 86400000, // 缓存有效期24小时(单位:毫秒)
    cacheMaxEntries: 5 // 最多缓存5个密钥
});

该库会自动管理缓存的刷新,当遇到未知的kid时,会主动从JWKS端点拉取最新密钥。

2. 自定义内存缓存(如需更灵活控制)

如果需要手动实现缓存逻辑,可以用内存对象存储密钥并设置过期时间:

let cachedKeys = {};
let cacheExpiry = 0;

const getSigningKeys = async (header) => {
    const now = Date.now();
    // 缓存过期或无对应kid时,重新拉取密钥
    if (now > cacheExpiry || !cachedKeys[header.kid]) {
        const response = await fetch(discoveryKeysEndpoint);
        const jwks = await response.json();
        cachedKeys = jwks.keys.reduce((map, key) => {
            map[key.kid] = key.publicKey || key.rsaPublicKey;
            return map;
        }, {});
        cacheExpiry = now + 86400000; // 设置24小时后过期
    }
    return cachedKeys[header.kid];
};

3. 处理密钥轮换的边界情况

  • 当验证令牌遇到kid不存在的情况,立即强制刷新缓存后重试验证
  • 不要只缓存单个密钥,保留JWKS返回的所有密钥,确保新旧令牌都能正常验证

内容的提问来源于stack exchange,提问作者Gaurav Mantri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 07:35:20