本文介绍如何在Microsoft.Identity.Web中配置令牌解密证书,以便应用程序可以解密来自Microsoft Identity Platform的加密令牌。
默认情况下,Microsoft 标识平台将令牌(ID 令牌、SAML 令牌)作为已签名但未加密的 JWT 颁发。 截获令牌的任何中介都可以读取其声明信息。 对于处理敏感声明或在严格符合性环境中运行的应用程序,Microsoft 标识平台支持 ken 加密。 启用后,标识平台使用向应用程序注册的公钥加密令牌有效负载。 只有保存相应私钥的应用程序才能解密和读取令牌。
令牌加密的工作原理
- 使用公钥/私钥对生成证书。
- 将 公钥(
.cer文件)上传到 Microsoft Entra ID 中的应用注册。 - 当Microsoft 标识平台为应用程序颁发令牌时,它会使用公钥加密令牌。
- 应用程序在处理声明之前使用 私钥 解密令牌。
加密使用两层方案:令牌有效负载使用对称内容加密密钥进行加密,该密钥使用公钥进行包装(加密)。 Microsoft Entra支持 RSA-OAEP 和 RSA-OAEP-256 密钥包装算法。
确定何时配置令牌解密
当应用程序满足以下条件之一时配置令牌解密:
- 接收加密的 SAML 令牌 - 企业应用程序,这些应用程序使用基于 SAML 的单一登录,并且出于合规性或法规原因需要加密的 SAML 断言。
- 接收加密的 ID 令牌,Web 应用程序选择对 ID 令牌进行加密,以防止在传输过程中读取敏感声明(组成员身份、自定义声明)。
- 在高安全性环境中运行 — 政府、财务或医疗保健方案中的应用程序,其中令牌保密由策略授权。
注释
令牌加密是可选的。 大多数应用程序不需要它。 只有满足特定要求时才启用令牌加密,因为它增加了操作复杂性(证书管理、轮换),并使得故障排除更加困难。
满足先决条件
在配置令牌解密之前,请验证以下要求:
-
一个具有私钥的 X.509 证书 — 需要使用
.pfx(PKCS#12) 格式的证书,或存储在应用程序可访问的位置(Azure 密钥保管库、证书存储或文件系统)。 解密令牌需要私钥。 - 配置用于令牌加密的应用注册 — 在 Microsoft Entra ID 中将证书的公钥上传到应用注册。 请参阅本文后面的 “注册解密证书 ”。
-
Microsoft.Identity.Web 2.1.0 或更高版本 - 从 Microsoft.Identity.Web 2.1.0 及更高版本开始,
TokenDecryptionCredentials配置属性是可用的。
在 appsettings.json 中配置令牌解密
Microsoft.Identity.Web 使用 TokenDecryptionCredentials 配置部分中的 AzureAd 数组。 此数组遵循与 ClientCredentials 相同的凭据说明格式,因此可以从Azure 密钥保管库、证书存储、文件路径或 Base64 编码字符串加载解密证书。
设置基本配置
以下示例演示从Azure 密钥保管库加载解密证书的最低配置:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "your-tenant-id",
"ClientId": "your-client-id",
"CallbackPath": "/signin-oidc",
"TokenDecryptionCredentials": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://mykeyvault.vault.azure.net",
"KeyVaultCertificateName": "MyCertificate"
}
]
}
}
无需其他代码。 当 Microsoft.Identity.Web 检测到 TokenDecryptionCredentials 配置时,它会自动加载指定的证书,并将其注册在 OpenID Connect 身份验证处理程序中用于令牌解密。
选择凭据源
数组 TokenDecryptionCredentials 支持与 ClientCredentials 相同的源类型。 下表汇总了每个选项:
| 来源类型 | 说明 | 必需的属性 |
|---|---|---|
| KeyVault | 从Azure 密钥保管库加载证书。 建议用于生产。 |
KeyVaultUrl、KeyVaultCertificateName |
| StoreWithThumbprint | 通过指纹标识符从本地证书存储加载。 |
CertificateStorePath、CertificateThumbprint |
| StoreWithDistinguishedName | 按主题可分辨名称从本地证书存储加载。 |
CertificateStorePath、CertificateDistinguishedName |
| 路径 | 从文件系统中的 .pfx 文件加载。 |
CertificateDiskPath、CertificatePassword |
| Base64Encoded | 从 Base64 编码的 .pfx 字符串加载(适用于环境变量)。 |
Base64EncodedValue |
密钥保管库(建议用于生产)
以下配置从Azure 密钥保管库加载解密证书:
{
"TokenDecryptionCredentials": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://mykeyvault.vault.azure.net",
"KeyVaultCertificateName": "TokenDecryptionCert"
}
]
}
应用程序的托管标识或服务主体必须在 密钥保管库 证书上具有 Get 和 List 权限。
证书存储(Windows)
以下配置通过指纹从Windows证书存储中加载证书:
{
"TokenDecryptionCredentials": [
{
"SourceType": "StoreWithThumbprint",
"CertificateStorePath": "CurrentUser/My",
"CertificateThumbprint": "A1B2C3D4E5F6..."
}
]
}
文件路径
以下配置从 .pfx 磁盘上的文件加载证书:
{
"TokenDecryptionCredentials": [
{
"SourceType": "Path",
"CertificateDiskPath": "/var/ssl/private/decrypt-cert.pfx",
"CertificatePassword": "your-certificate-password"
}
]
}
警告
避免在生产环境中存储 appsettings.json 的证书密码。 请改用环境变量、Azure 密钥保管库引用或机密管理器。
Base64 编码
以下配置从 Base64 编码的字符串加载证书:
{
"TokenDecryptionCredentials": [
{
"SourceType": "Base64Encoded",
"Base64EncodedValue": "MIIJ..."
}
]
}
通过环境变量或 CI/CD 管道机密注入证书时,此选项非常有用。
配置多个解密证书
可以在数组中 TokenDecryptionCredentials 指定多个证书。 Microsoft.Identity.Web 会按顺序尝试每一个证书,直到有一个成功解密令牌。 此功能对于 证书轮换 至关重要(请参阅 证书轮换)。
{
"TokenDecryptionCredentials": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://mykeyvault.vault.azure.net",
"KeyVaultCertificateName": "TokenDecryptionCert-New"
},
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://mykeyvault.vault.azure.net",
"KeyVaultCertificateName": "TokenDecryptionCert-Old"
}
]
}
在 Microsoft Entra ID 中注册解密证书
若要使 Microsoft 身份验证平台为您的应用程序加密令牌,必须将证书的公钥上传到您的应用注册:
- 登录到 Microsoft Entra 管理中心。
- 导航到 Identity>Applications>应用注册并选择应用程序。
- 选择“证书和机密”“证书”>“上传证书”>。
- 上传
.cer解密证书的公钥文件。 - 上传后,请注意 指纹 值 — 它必须与应用程序使用的证书匹配。
为应用程序启用令牌加密
上传证书后,必须将应用程序配置为接收加密令牌。 此配置当前可通过 Microsoft 图形 API 或 PowerShell 获得:
使用 Microsoft Graph PowerShell:
# Get the key credential ID of the uploaded certificate
$app = Get-MgApplication -Filter "appId eq 'your-client-id'"
$keyId = ($app.KeyCredentials | Where-Object { $_.DisplayName -eq "CN=TokenDecryptionCert" }).KeyId
# Set the token encryption key ID
Update-MgApplication -ApplicationId $app.Id -BodyParameter @{
"tokenEncryptionKeyId" = $keyId
}
重要
在应用程序对象上的 tokenEncryptionKeyId 属性标识 Microsoft Entra 用于加密令牌的上传证书。 一次只能有一个加密密钥处于活动状态。
轮换解密证书
令牌解密的证书轮换需要谨慎的分阶段方法,以避免停机:
轮换步骤
- 生成新证书 - 使用私钥创建新的 X.509 证书。
-
将新证书添加到应用程序配置 - 将新证书与现有证书一起添加到
TokenDecryptionCredentials数组。 将新证书放在数组的首位。 -
上传新的公钥 — 在Microsoft Entra中的应用注册中上传新证书的
.cer文件。 - 部署您的应用程序,部署更新的配置,使您的应用程序可以使用任何一个证书解密令牌。
-
切换活动加密密钥 - 更新
tokenEncryptionKeyId应用程序对象以指向新证书keyId。 - 验证 — 确认应用程序已成功解密使用新证书加密的令牌。
- 删除旧证书 — 宽限期(至少 24 小时允许缓存令牌过期)之后,请从应用注册和应用程序配置中删除旧证书。
轮换期间的配置
在轮换窗口中,您的TokenDecryptionCredentials应包含这两个证书:
{
"TokenDecryptionCredentials": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://mykeyvault.vault.azure.net",
"KeyVaultCertificateName": "TokenDecryptionCert-2026"
},
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://mykeyvault.vault.azure.net",
"KeyVaultCertificateName": "TokenDecryptionCert-2025"
}
]
}
小窍门
通过使用Azure 密钥保管库的自动轮换功能以及密钥保管库事件通知来触发应用程序重新部署,自动轮换证书。
排查令牌解密问题
使用以下指南诊断和解决常见的令牌解密问题。
令牌解密失败
症状: 处理令牌时,应用程序会引发 SecurityTokenDecryptionFailedException 或返回 401/500 错误。
常见原因:
| 原因 | 解决方案 |
|---|---|
| 找不到证书 | 验证证书是否存在于配置的位置(密钥保管库、存储或文件路径)。 检查应用程序是否具有访问它所需的权限。 |
| 证书错误 | 验证应用程序配置中的证书指纹是否与上传到应用注册的证书匹配。 |
tokenEncryptionKeyId 未设置 |
在 Microsoft Entra 中设置应用程序对象的 tokenEncryptionKeyId 属性。 如果没有此属性,标识平台不会加密令牌。 |
缺少私钥
症状:CryptographicException: The certificate key is not accessible 或 InvalidOperationException: Certificate does not have a private key。
原因和解决方法:
-
在没有私钥的情况下导出的证书 - 以格式重新导出证书
.pfx,并确保在导出过程中包含私钥。 密钥保管库访问策略 - 使用Azure 密钥保管库时,确保应用程序的标识对Certificates 和Secrets 具有Get 权限。 私钥以机密的形式存储在密钥保管库中。- 证书存储权限 - 在 Windows 上,验证应用程序池标识或服务帐户是否具有私钥的读取权限。 使用证书存储 MMC 管理单元中的 “管理私钥 ”选项。
算法不匹配
症状:SecurityTokenDecryptionFailedException 带有指示不受支持的算法的消息。
原因和解决方法:
- 不支持的密钥类型,Microsoft Entra 支持 RSA 证书用于令牌加密。 确保证书使用 RSA 密钥对(而不是 EC/ECDSA)。
- 密钥大小太小 - 使用至少 2048 位的密钥大小。 小于 2048 位的 RSA 密钥可能会被拒绝。
- 不支持算法 — Microsoft Entra 使用 RSA-OAEP 进行密钥包装。 确保证书和应用程序基础结构支持此算法。
未颁发加密令牌
症状: 即使配置了令牌解密,应用程序也会接收未加密的令牌。
原因和解决方法:
-
tokenEncryptionKeyId未配置 — 必须通过 Microsoft Graph 显式设置此属性。 仅上传证书是不够的。 - 应用注册中证书已过期 - 请验证上传到您的应用注册中的证书是否已过期。 根据需要上传新证书。
- 访问令牌未加密 - 令牌加密仅适用于 ID 令牌 和 SAML 令牌 。 来自Microsoft Entra的访问令牌未使用证书进行加密。
比较令牌解密和客户端凭据
令牌解密凭据与客户端凭据不同。 应用程序可以为这两者使用相同的证书,也可以使用单独的证书。
以下示例演示了一个配置,该配置对身份验证和令牌解密使用相同的密钥保管库证书:
{
"AzureAd": {
"ClientCredentials": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://mykeyvault.vault.azure.net",
"KeyVaultCertificateName": "AppAuthCert"
}
],
"TokenDecryptionCredentials": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://mykeyvault.vault.azure.net",
"KeyVaultCertificateName": "AppAuthCert"
}
]
}
}
注释
将同一证书用于这两个目的时,证书必须具有 KeyEncipherment 密钥用法并使用 KeyExchange 密钥规范(而不是 Signature)。 用KeySpec = Signature生成的证书适用于客户端凭据,但在令牌解密时失败。
遵循最佳做法
实现令牌解密时,请应用这些建议。
使用 Azure 密钥保管库 — 将解密证书存储在密钥保管库中,用于集中管理、访问控制和审核日志记录。
规划轮换 - 在部署令牌加密之前始终具有轮换策略。 在轮换窗口中包括新证书和旧证书。
使用 RSA 2048 位或更大的密钥 — 确保证书使用至少 2048 位的 RSA 密钥来确保足够的安全性。
监控证书过期 - 在 Azure 密钥保管库 或你的监控系统中设置警报,以便在证书过期之前通知你。
在过渡环境中进行测试 — 在非生产环境中验证令牌加密和解密,然后再在生产环境中启用令牌加密和解密。
不要在源代码管理中存储私钥 — 将密钥保管库、环境变量或机密管理器用于证书存储。
不要在轮换期间过早删除旧证书 - 使两个证书至少保持活动状态 24 小时,以允许缓存的令牌过期。
如果不配置解密证书,请不要启用令牌加密 — 如果应用程序无法解密令牌,应用程序将无法处理令牌。