Key rotation for OpenIddict uses the .NET Data Protection API to protect signing keys at rest.
It is best practice to configure Data Protection persistence explicitly
If Data Protection is not explicitly configured, generated keys may not be accessible after a server restart or in a load-balanced environment. The .NET Data Protection system will attempt to configure a persistence store based on the environment, but it may fall back to an ephemeral provider.
For more information, see Configuring Data Protection from Microsoft.
Key Persistence
Data Protection keys should be persisted to ensure protected material is available after a server restart or in load-balanced environments. Keys can be persisted using several different storage mechanisms such as a database, file system, or Azure Blob Storage.
For the following examples, the Microsoft.AspNetCore.DataProtection NuGet package is required.
Persist to Database
To persist keys to a database, the Microsoft.AspNetCore.DataProtection.EntityFrameworkCore package can be used. This provides the PersistKeysToDbContext extension method, which accepts a DbContext that implements IDataProtectionKeyContext.
services.AddDataProtection()
.PersistKeysToDbContext<ApplicationDbContext>();
Persist to Azure Blob Storage
To use Azure Blob Storage, reference the Azure.Extensions.AspNetCore.DataProtection.Blobs NuGet package.
// Set up the connection string and container name
string connectionString = "<Your_Azure_Storage_Connection_String>";
string containerName = "dataprotection-keys";
// Create a BlobServiceClient
var blobServiceClient = new BlobServiceClient(connectionString);
// Create the container if it doesn't exist
var blobContainerClient = blobServiceClient.GetBlobContainerClient(containerName);
blobContainerClient.CreateIfNotExists();
// Configure Data Protection to use Azure Blob Storage
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(blobContainerClient.GetBlobClient("keys.xml"));
Persist to File System
To persist Data Protection keys on the host file system, use the PersistKeysToFileSystem method.
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo("/path/to/keys"));
Persist to Registry (Windows Only)
Keys can also be persisted to the Windows Registry.
// Create or open the registry key
var registryKey = Registry.CurrentUser.CreateSubKey(@"Software\MyApp\DataProtectionKeys");
services.AddDataProtection()
.PersistKeysToRegistry(registryKey);
Key Protection
To ensure data security, it is best practice to protect your Data Protection keys. Several mechanisms are provided, such as Azure Key Vault or X.509 certificates.
To protect your keys with Azure Key Vault, use the ProtectKeysWithAzureKeyVault method.
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri("{BLOB STORAGE URL}"), new DefaultAzureCredential())
.ProtectKeysWithAzureKeyVault(new Uri("{KEY VAULT URL}"), new DefaultAzureCredential());
To protect your keys with a certificate, use the ProtectKeysWithCertificate method.
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"{DIRECTORY}"))
.ProtectKeysWithCertificate(new X509Certificate2("{CERTIFICATE PATH}", "{PASSWORD}"));
Load-Balanced Environments
To run OpenIddict with key rotation in a load-balanced environment, an external persisted store is required. This could be a database or Azure Blob Storage. Each application instance must have the same ApplicationName configured for Data Protection. This can be set using the SetApplicationName extension method:
builder.Services.AddDataProtection()
.SetApplicationName("{APPLICATION NAME}");