Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly configure OpenIddict with ASP.NET Core DataProtection

I am trying to setup OpenIddict using ASP.NET Core DataProtection however I keep getting an exception when attempting to start the application:

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.

Now I understand what the error wants me to do, I need to add a signing key/encryption certificate, but why?

Isn't the whole point of using the DataProtection that this part is automated and doesn't require you to add an explicit signing key/encryption certificate? According to the documentation the DataProtection should be used to encrypt all the keys except for JWT id tokens.

This is the current code:

            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();
                });
like image 392
Thodor20 Avatar asked Sep 02 '25 10:09

Thodor20


1 Answers

The data protection API is involved inside the Cookie handler, and its job is to encrypt the session cookie. The session cookie contains the ClaimsPrincipal User object and optionally your tokens.

Just like this picture shows:

enter image description here

By default the Data Protection API creates its own key-ring and that's great! But in production you want to make sure the keyring stays the same across deployments. If not, if you redeploy, then you might not be able to accept previously generated cookies.

I did blog about this here: https://www.edument.se/post/storing-the-asp-net-core-data-protection-key-ring-in-azure-key-vault?lang=en

However, the Data Protection API is not involved in managing the token signing keys. Data Protection is only about protecting the session cookie. So you need to provide a separate private key (persisted externally), so the key is the same across deployments of your service.

Data Protection API is only about protecting things, not what to protect. So that's why you need a separate key/certificate.

I did a blog post about how you can bypass the protection and peek inside the cookies at: https://nestenius.se/2023/11/22/exploring-what-is-inside-the-asp-net-core-cookies/

like image 119
Tore Nestenius Avatar answered Sep 04 '25 08:09

Tore Nestenius