Kestrel supports dynamic server certificate selection through HttpsConnectionAdapterOptions.ServerCertificateSelector. However, the most discoverable configuration paths accept an X509Certificate2 or assign HttpsConnectionAdapterOptions.ServerCertificate, which captures one certificate while the application is starting. This is easy to misuse with certificate platforms that rotate material behind a DI-managed provider. Many service teams assume that the certificate is configured once for the entire application lifetime, or that updating the provider automatically updates the certificate already assigned to Kestrel. In practice, Kestrel continues presenting the captured certificate until the endpoint or process is recreated.
A first-class DI-backed configuration path would help teams manage certificates effectively by making the intended lifetime explicit:
- Resolve a long-lived certificate provider from application services.
- Ask that provider for its current certificate when each new TLS connection is authenticated.
- Keep refresh, validation, overlap and disposal inside the provider rather than application startup code.
The existing workaround is:
var certificateProvider = listenOptions.ApplicationServices.GetRequiredService<IServerCertificateProvider>();
listenOptions.UseHttps(httpsOptions =>
{
httpsOptions.ServerCertificateSelector = (_, serverName) => certificateProvider.GetCurrentCertificate(serverName);
});
This works, but it requires teams to understand that ServerCertificate is a snapshot, discover ServerCertificateSelector, find the application service provider exposed by Kestrel, and compose the lifetimes correctly. Incorrect wiring still looks valid and generally fails only after the first live rotation.
Proposed direction
Add a focused ListenOptions extension that resolves a selector through Kestrel's application services and installs the existing ServerCertificateSelector. An illustrative API shape is:
namespace Microsoft.AspNetCore.Hosting;
public static partial class ListenOptionsHttpsExtensions
{
public static ListenOptions UseHttps(
this ListenOptions listenOptions,
Func<IServiceProvider, Func<ConnectionContext?, string?, X509Certificate2?>> serverCertificateSelectorFactory);
}
The factory would run once while configuring the endpoint. The returned selector would run for each new TLS connection:
listenOptions.UseHttps(services =>
{
var certificateProvider = services.GetRequiredService<IServerCertificateProvider>();
return (_, serverName) => certificateProvider.GetCurrentCertificate(serverName);
});
Behaviour and ownership
- Selection remains synchronous and may run concurrently. Providers should return validated in-memory material and perform external refresh asynchronously.
- The provider owns returned certificates. Kestrel and application wiring must not dispose borrowed instances.
- The provider is responsible for retaining a last-known-good certificate and defining overlap and retirement of old material.
- Selection affects new TLS handshakes only. Existing connections retain their established TLS state.
- The selector receives the existing
ConnectionContext and SNI server name without losing information.
- Existing HTTPS settings and defaults remain unchanged except that the installed selector takes precedence over a fixed
ServerCertificate.
- Interaction with an already configured selector should be explicit, preferably by rejecting conflicting configuration rather than silently replacing it.
Alternative designs
Add an Action<HttpsConnectionAdapterOptions, IServiceProvider> overload
A general DI-aware HTTPS configuration overload would enable the scenario, but it would not draw attention to certificate lifetime or prevent callers from resolving and assigning one certificate during configuration.
Use Kestrel configuration reload
dotnet/aspnetcore#32351, implemented by dotnet/aspnetcore#50251, supports automatic rotation for certificates loaded from Kestrel's file-based configuration. This proposal concerns certificates supplied by live DI-managed providers and is therefore not a duplicate.
Related work
- dotnet/aspnetcore#60380 concerns retiring existing connections that authenticated with an old certificate. This proposal affects certificate selection for new connections only.
- dotnet/aspnetcore#6968 concerned asynchronous certificate selection. This proposal deliberately retains the existing synchronous selector and expects providers to refresh material outside the handshake callback.
- dotnet/runtime#135206 proposes the corresponding HttpClientFactory helper for DI-backed rotating outbound mTLS client certificates. This proposal covers inbound server certificates selected by Kestrel.
Kestrel supports dynamic server certificate selection through
HttpsConnectionAdapterOptions.ServerCertificateSelector. However, the most discoverable configuration paths accept anX509Certificate2or assignHttpsConnectionAdapterOptions.ServerCertificate, which captures one certificate while the application is starting. This is easy to misuse with certificate platforms that rotate material behind a DI-managed provider. Many service teams assume that the certificate is configured once for the entire application lifetime, or that updating the provider automatically updates the certificate already assigned to Kestrel. In practice, Kestrel continues presenting the captured certificate until the endpoint or process is recreated.A first-class DI-backed configuration path would help teams manage certificates effectively by making the intended lifetime explicit:
The existing workaround is:
This works, but it requires teams to understand that
ServerCertificateis a snapshot, discoverServerCertificateSelector, find the application service provider exposed by Kestrel, and compose the lifetimes correctly. Incorrect wiring still looks valid and generally fails only after the first live rotation.Proposed direction
Add a focused
ListenOptionsextension that resolves a selector through Kestrel's application services and installs the existingServerCertificateSelector. An illustrative API shape is:The factory would run once while configuring the endpoint. The returned selector would run for each new TLS connection:
Behaviour and ownership
ConnectionContextand SNI server name without losing information.ServerCertificate.Alternative designs
Add an
Action<HttpsConnectionAdapterOptions, IServiceProvider>overloadA general DI-aware HTTPS configuration overload would enable the scenario, but it would not draw attention to certificate lifetime or prevent callers from resolving and assigning one certificate during configuration.
Use Kestrel configuration reload
dotnet/aspnetcore#32351, implemented by dotnet/aspnetcore#50251, supports automatic rotation for certificates loaded from Kestrel's file-based configuration. This proposal concerns certificates supplied by live DI-managed providers and is therefore not a duplicate.
Related work