DuendeSoftware / Support

Support for Duende Software products
21 stars 0 forks source link

Signing key location with manual key rotation? #1460

Closed bwalls040971 closed 3 weeks ago

bwalls040971 commented 1 month ago

I cannot seem to find where my signing key is being stored. I have set KeyManagement.Enabled = false and a KeyManagement.KeyPath to a shared location. I then call AddSigningCredential to add my certificate. I can login with my other applications, so it appears to be working, but I am confused as to why I never see a signing key like I do with the Data Protection keys.

I have cleared the Keys table in the database and I call builder.Services.Remove for a typeof(SigningKeyStore) after I call AddOperationalStore. I am under the impression that the key should be stored in the KeyManagement.KeyPath location at this point, but I never see anything in the path. I am using a similar share path and setup for Data Protection and I do see the DP keys created.

I do not see a local 'Keys' directory in the app, nor do I do not have an entry in the keys database table. Where is my signing key at this point?

Below is the code I am using in Program.cs. Should I be manually adding the signing credential key differently?

string identityConnectionString = builder.Configuration.GetConnectionString("IdentityServerConnection");

// Load x.509 data protection certificate from the LocalMachine certificate store.
var certificate = GetCertificateFromStore(configuration.GetValue<string>("NetworkSettings:DataProtection:Certificate:Thumbprint"));

// Configure ASP.NET Data Protection
builder.Services.AddDataProtection()
    .ProtectKeysWithCertificate(certificate)  // Use X.509 certificate for encryption
    .PersistKeysToFileSystem(new DirectoryInfo(configuration.GetValue<string>("NetworkSettings:DataProtection:Path")))  // Shared key storage
    .SetApplicationName(configuration.GetValue<string>("NetworkSettings:DataProtection:AppName"));

// Load x.509 signing certificate from the LocalMachine certificate store.
var signingCertificate = GetCertificateFromStore(configuration.GetValue<string>("NetworkSettings:IdentityServer:Certificate:Thumbprint"));

// Add Identity Server.
builder.Services.AddIdentityServer(options =>
{
    options.KeyManagement.Enabled = false; // Disable automatic key management
    options.KeyManagement.KeyPath = configuration.GetValue<string>("NetworkSettings:IdentityServer:SigningKeyPath"); // Path for signing keys

    options.Events.RaiseErrorEvents = true;
    options.Events.RaiseInformationEvents = true;
    options.Events.RaiseFailureEvents = true;
    options.Events.RaiseSuccessEvents = true;

    // see https://docs.duendesoftware.com/identityserver/v5/basics/resources
    options.EmitStaticAudienceClaim = true;
})
.AddSigningCredential(signingCertificate)  // Use X.509 certificate for signing tokens.
.AddConfigurationStore(options =>
{
    options.ConfigureDbContext = b => b.UseSqlServer(identityConnectionString);
})
.AddOperationalStore(options =>
{
    options.ConfigureDbContext = b => b.UseSqlServer(identityConnectionString);
    options.EnableTokenCleanup = false; // Instead, we use a SQL Agent Job to call PersistedGrantCleanup stored procedure (more efficient).
})
// Adds our CustomProfileService into DI.
.AddProfileService<CustomProfileService>();

// Remove the database key store from the DI container (added as part of the OperationalStore).
var efKeyStoreDescriptor = builder.Services.FirstOrDefault(d => d.ImplementationType == typeof(SigningKeyStore));
builder.Services.Remove(efKeyStoreDescriptor);

....

var app = builder.Build();

I am using IdentityServer v6.05 / .Net 6. Thank you.

AndersAbel commented 3 weeks ago

The KeyManagement options will not be used if automatic key management is disabled.

When you call AddSigningCredential() with a certificate the certificate is read and the data is then kept in memory. There is no key to save to disk/database - your certificate is the key.

bwalls040971 commented 3 weeks ago

The KeyManagement options will not be used if automatic key management is disabled.

When you call AddSigningCredential() with a certificate the certificate is read and the data is then kept in memory. There is no key to save to disk/database - your certificate is the key.

Got it - thank you for the clarification!