Why does .NET Core data protection invalidate my refresh token in Duende identity server?

81 Views Asked by At

I am working on a project with Duende Identity Server 6. This is a long running project, so it has been operational for some time. The project also consists of a power automate connector that has a connection based on OIDC with refresh tokens.

Last week we found some issues regarding data protection (exception: "Key not found in keyring"). Therefore we decided to move the storage of our data protection keys from Azure Blob Storage to our database since we assume that this is probably more stable.

We were aware that this change would cause all existing data protection keys to be deleted and so all data protected by these keys will become invalid.

...
services.AddDbContext<DataProtectionKeysContext>(options => options.UseSqlServer(
    Configuration["IdentityDatabase"], 
    b => b.MigrationsAssembly("IdentityServer")));

X509Certificate2 dataProtectionCertificate = new X509Certificate2(
    Path.Combine(_env.ContentRootPath, Configuration["DataProtectionCertificate"]),
    Configuration["DataProtectionCertificatePassword"], 
    X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);

services.AddDataProtection()
    .SetApplicationName(Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME"))
    .PersistKeysToDbContext<DataProtectionKeysContext>()
    .ProtectKeysWithCertificate(dataProtectionCertificate);
...

Identity Server uses data protection by default and has a table named Dataprotectionkeys. We decided to reuse that table for general data protection.

Data protection is not explicitly setup for identity server, so defaults are used and we see the refresh tokens being present in the persisted grant table with DataProtected:true, so we assume that this is in fact operational.

After changing the storage we find that somehow power automate connections that were created after the update fail after about a day. So somehow it seems that tokens are invalidated too soon.

Perhaps we should not have reused the database table, that is something we can still try, but if anyone has another idea that would be very helpful.

Thanks for thinking along

1

There are 1 best solutions below

0
Tore Nestenius On

The Data Protection API should be explicitly configured in all services that go to production, including IdentityServer.

Especially, if you try to run multiple instances of a service behind a load balancer.

Duende has some documentation about it here: ASP.NET Core Data Protection

For fun, I did a blog post about creating your own storage at : Storing the ASP.NET Core Data Protection Key Ring in Azure Key Vault

This discussion also has some interesting facts. https://github.com/dotnet/aspnetcore/issues/26786

So, the question is, what is your actual question?

If the application name or purposes change, then already encrypted data will be lost.

You can find all the purposes used in the log, if you change the log level to verbose for the data protection API, sample entry:

Performing unprotect operation to key {b0ea74d2-bfa4-4eee-b9fb-a5383ddd58ea} with purposes ('C:\code\Data Protection API - Demo project\Data Protection API - Start project\', 'Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware', 'cookie', 'v2').