如何使用 ASP.NET Core DataProtection 正确配置 OpenIddict

Posted

技术标签:

【中文标题】如何使用 ASP.NET Core DataProtection 正确配置 OpenIddict【英文标题】:How to properly configure OpenIddict with ASP.NET Core DataProtection 【发布时间】:2022-01-15 23:12:04 【问题描述】:

我正在尝试使用 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();
                );

【问题讨论】:

【参考方案1】:

数据保护 API 包含在 Cookie 处理程序中,它的工作是加密会话 cookie。会话 cookie 包含 ClaimsPrincipal 用户对象和可选的令牌。

就像这张图所示:

默认情况下,数据保护 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 只是保护事物,而不是保护什么。这就是为什么您需要单独获取密钥/证书的原因。

【讨论】:

感谢您的回答,我的数据保护 API 工作正常,这不是问题。我已经使用 Azure Blob Storage/Key Vault 对其进行了配置。我只有将它与 OpenIddict 集成时遇到问题 查看我更新的问题,是否澄清/帮助? 不,这不是问题,OpenIddict 在选项构建器中提供了一个“UseDataProtection()”方法,以便能够使用 DataProtection API 构建访问令牌等:Source。但是,选项生成器仍然要求我提供我认为不需要的签名密钥/证书。 在许多组织中,签名密钥是一件重要的事情,您希望执行各种策略,例如密钥轮换。是的,我认为数据保护 API 只专注于一项任务,加密数据和管理自己的密钥/密钥环是件好事。它并不关心它处理什么。与 HTTPS 证书类似,您也需要单独提供一份... 在 OpenIDConnect 中,您还拥有多种密钥类型、RSA 和 3 种 ECDSA,因此在您看来,数据保护也必须了解所有这些。因此分离职责简化了数据保护 api。

以上是关于如何使用 ASP.NET Core DataProtection 正确配置 OpenIddict的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.Net Core 使用 内存缓存

如何使用 EF Core 在 ASP.NET Core 中取消应用迁移

如何使用 dotnet cli 命令以 VB.NET 语言创建 ASP.NET Core 项目?

如何在 ASP.NET Core 中使用 SqlClient?

如何在 ASP.NET Core 中使用 Route 特性

如何使用 ASP.NET Core 进行流式传输