我正在尝试使用 ASP.NET Core DataProtection 设置 OpenIddict,但是在尝试启动应用程序时我不断收到异常:
InvalidOperationException: At least one encryption key must be registered in the OpenIddict server options. Consider registering a certificate using 'services.AddOpenIddict().AddServer().AddEncryptionCertificate()' or 'services.AddOpenIddict().AddServer().AddDevelopmentEncryptionCertificate()' or call 'services.AddOpenIddict().AddServer().AddEphemeralEncryptionKey()' to use an ephemeral key.
现在我明白错误要我做什么,我需要添加签名密钥/加密证书,但为什么?
使用 DataProtection 的全部意义不就是这部分是自动化的并且不需要您添加显式签名密钥/加密证书吗? 根据文档,DataProtection 应用于加密除 JWT id 令牌之外的所有密钥。
这是当前代码:
if (authenticationOptions.DataProtection.TokenProtection.Enabled)
services
.AddDataProtection(options =>
{
options.ApplicationDiscriminator = applicationOptions.ShortName;
})
.SetApplicationName(applicationOptions.Name)
.SetDefaultKeyLifetime(TimeSpan.FromDays(authenticationOptions.DataProtection.TokenProtection.LifeTime))
.PersistKeysToAzureBlobStorage(CreateDataProtectionBlobClient(azureOptions.BlobStorageUrl, authenticationOptions.DataProtection, azureCredential))
.ProtectKeysWithAzureKeyVault(completeKeyVaultUri, azureCredential);
}
services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore()
.UseDbContext<ApplicationDbContext>()
.ReplaceDefaultEntities<long>(); ;
})
.AddServer(options =>
{
options.SetAuthorizationEndpointUris("connect/auth");
options.SetTokenEndpointUris("/connect/token");
options.AllowAuthorizationCodeFlow();
options.AllowClientCredentialsFlow();
options.AllowRefreshTokenFlow();
options.UseAspNetCore()
.EnableAuthorizationEndpointPassthrough()
.EnableTokenEndpointPassthrough();
options.UseDataProtection();
//options.AddEphemeralSigningKey();
//options.AddEphemeralEncryptionKey();
})
.AddValidation(options =>
{
options.UseLocalServer();
options.UseAspNetCore();
options.UseDataProtection();
});
数据保护API涉及Cookie处理程序内部,其作用是对会话cookie进行加密。会话 cookie 包含 ClaimsPrincipal User 对象和可选的您的令牌。
就像这张图所示:
默认情况下,数据保护 API 创建自己的密钥环,这太棒了!但在生产中,您希望确保密钥环在部署中保持不变。如果没有,如果您重新部署,那么您可能无法接受之前生成的 cookie。
我在这里写了关于此的博客: https://www.edument.se/post/storing-the-asp-net-core-data-protection-key-ring-in-azure-key-vault?lang=en
但是,数据保护 API 不参与管理令牌签名密钥。数据保护仅涉及保护会话 cookie。因此,您需要提供一个单独的私钥(在外部保留),因此该密钥在服务的各个部署中都是相同的。
数据保护API只是保护事物,而不是保护什么。这就是为什么您需要单独的密钥/证书。
我写了一篇关于如何绕过保护并查看 Cookie 内部的博客文章:https://nestenius.se/2023/11/22/exploring-what-is-inside-the-asp-net-core -饼干/
简短的回答是,使用
UseDataProtection
并不能取代对证书的需求,因此注释掉以下行:
//options.AddEphemeralSigningKey();
//options.AddEphemeralEncryptionKey();
意味着您没有证书,因此 OpenIddict 会抛出错误。
您可以将数据保护密钥和证书存储在 Azure 中(例如 Blob 和 Key Vault)。您只需对两者进行所有配置即可。
(像OP一样,我也认为添加
.UseDataProtection()
和Azure中保留的密钥意味着我可以删除证书 - 但可惜,不......它们是两个完全不同的东西)