From d45774b1f32b33d111887874901726a7e0324153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Mon, 1 Jun 2026 08:06:55 +0200 Subject: [PATCH] Automatically register IOptionsChangeTokenSource implementations to enable cascade re-evaluation of options --- .../OpenIddictClientAspNetCoreConfiguration.cs | 15 ++++++++++++++- .../OpenIddictClientAspNetCoreExtensions.cs | 3 +++ .../OpenIddictClientOwinConfiguration.cs | 15 ++++++++++++++- .../OpenIddictClientOwinExtensions.cs | 3 +++ ...ictValidationServerIntegrationConfiguration.cs | 15 ++++++++++++++- ...IddictValidationServerIntegrationExtensions.cs | 3 +++ 6 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreConfiguration.cs b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreConfiguration.cs index 88124285..28683114 100644 --- a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreConfiguration.cs +++ b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreConfiguration.cs @@ -7,6 +7,7 @@ using System.ComponentModel; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Microsoft.Extensions.Primitives; namespace OpenIddict.Client.AspNetCore; @@ -19,7 +20,8 @@ public sealed class OpenIddictClientAspNetCoreConfiguration : IConfigureOptions< IPostConfigureOptions, IPostConfigureOptions, IValidateOptions, - IValidateOptions + IValidateOptions, + IOptionsChangeTokenSource { private readonly IServiceProvider _provider; @@ -203,4 +205,15 @@ public sealed class OpenIddictClientAspNetCoreConfiguration : IConfigureOptions< return builder.Build(); } + + /// + IChangeToken IOptionsChangeTokenSource.GetChangeToken() => new CompositeChangeToken( + [ + // Force the options to be re-evaluated when the related instances from which they are populated are changed. + .. from source in _provider.GetServices>() + select source.GetChangeToken() + ]); + + /// + string? IOptionsChangeTokenSource.Name => Options.DefaultName; } diff --git a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreExtensions.cs b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreExtensions.cs index 6305d59c..21c2faeb 100644 --- a/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreExtensions.cs +++ b/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreExtensions.cs @@ -63,6 +63,9 @@ public static class OpenIddictClientAspNetCoreExtensions builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton< IValidateOptions, OpenIddictClientAspNetCoreConfiguration>()); + builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton< + IOptionsChangeTokenSource, OpenIddictClientAspNetCoreConfiguration>()); + return new OpenIddictClientAspNetCoreBuilder(builder.Services); } diff --git a/src/OpenIddict.Client.Owin/OpenIddictClientOwinConfiguration.cs b/src/OpenIddict.Client.Owin/OpenIddictClientOwinConfiguration.cs index 16a54024..cd5af07d 100644 --- a/src/OpenIddict.Client.Owin/OpenIddictClientOwinConfiguration.cs +++ b/src/OpenIddict.Client.Owin/OpenIddictClientOwinConfiguration.cs @@ -7,6 +7,7 @@ using System.ComponentModel; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Microsoft.Extensions.Primitives; using Owin; namespace OpenIddict.Client.Owin; @@ -17,7 +18,8 @@ namespace OpenIddict.Client.Owin; [EditorBrowsable(EditorBrowsableState.Advanced)] public sealed class OpenIddictClientOwinConfiguration : IConfigureOptions, IPostConfigureOptions, - IValidateOptions + IValidateOptions, + IOptionsChangeTokenSource { private readonly IServiceProvider _provider; @@ -117,4 +119,15 @@ public sealed class OpenIddictClientOwinConfiguration : IConfigureOptions + IChangeToken IOptionsChangeTokenSource.GetChangeToken() => new CompositeChangeToken( + [ + // Force the options to be re-evaluated when the related instances from which they are populated are changed. + .. from source in _provider.GetServices>() + select source.GetChangeToken() + ]); + + /// + string? IOptionsChangeTokenSource.Name => Options.DefaultName; } diff --git a/src/OpenIddict.Client.Owin/OpenIddictClientOwinExtensions.cs b/src/OpenIddict.Client.Owin/OpenIddictClientOwinExtensions.cs index 3dad0a7a..4229683a 100644 --- a/src/OpenIddict.Client.Owin/OpenIddictClientOwinExtensions.cs +++ b/src/OpenIddict.Client.Owin/OpenIddictClientOwinExtensions.cs @@ -56,6 +56,9 @@ public static class OpenIddictClientOwinExtensions builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton< IValidateOptions, OpenIddictClientOwinConfiguration>()); + builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton< + IOptionsChangeTokenSource, OpenIddictClientOwinConfiguration>()); + return new OpenIddictClientOwinBuilder(builder.Services); } diff --git a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs index 61eb3066..730313bc 100644 --- a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs +++ b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationConfiguration.cs @@ -7,6 +7,7 @@ using System.ComponentModel; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Microsoft.Extensions.Primitives; using OpenIddict.Server; namespace OpenIddict.Validation.ServerIntegration; @@ -16,7 +17,8 @@ namespace OpenIddict.Validation.ServerIntegration; /// [EditorBrowsable(EditorBrowsableState.Advanced)] public sealed class OpenIddictValidationServerIntegrationConfiguration : IConfigureOptions, - IValidateOptions + IValidateOptions, + IOptionsChangeTokenSource { private readonly IServiceProvider _provider; @@ -87,4 +89,15 @@ public sealed class OpenIddictValidationServerIntegrationConfiguration : IConfig return builder.Build(); } + + /// + IChangeToken IOptionsChangeTokenSource.GetChangeToken() => new CompositeChangeToken( + [ + // Force the options to be re-evaluated when the related instances from which they are populated are changed. + .. from source in _provider.GetServices>() + select source.GetChangeToken() + ]); + + /// + string? IOptionsChangeTokenSource.Name => Options.DefaultName; } diff --git a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationExtensions.cs b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationExtensions.cs index dbb4b121..128c631b 100644 --- a/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationExtensions.cs +++ b/src/OpenIddict.Validation.ServerIntegration/OpenIddictValidationServerIntegrationExtensions.cs @@ -34,6 +34,9 @@ public static class OpenIddictValidationServerIntegrationExtensions builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton< IValidateOptions, OpenIddictValidationServerIntegrationConfiguration>()); + builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton< + IOptionsChangeTokenSource, OpenIddictValidationServerIntegrationConfiguration>()); + return new OpenIddictValidationServerIntegrationBuilder(builder.Services); }