diff --git a/src/AspNetIdentity/IdentityServerBuilderExtensions.cs b/src/AspNetIdentity/IdentityServerBuilderExtensions.cs index 5618c519d..62e569dde 100644 --- a/src/AspNetIdentity/IdentityServerBuilderExtensions.cs +++ b/src/AspNetIdentity/IdentityServerBuilderExtensions.cs @@ -10,6 +10,8 @@ using Duende.IdentityServer.AspNetIdentity; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; +using Duende.IdentityServer.Configuration; namespace Microsoft.Extensions.DependencyInjection; @@ -81,6 +83,8 @@ public static IIdentityServerBuilder AddAspNetIdentity(this IIdentityServ builder.AddResourceOwnerValidator>(); builder.AddProfileService>(); + builder.Services.AddSingleton, UseAspNetIdentityCookieScheme>(); + return builder; } diff --git a/src/AspNetIdentity/PostConfigureIdentityServerOptions.cs b/src/AspNetIdentity/PostConfigureIdentityServerOptions.cs new file mode 100644 index 000000000..e6fcbfc58 --- /dev/null +++ b/src/AspNetIdentity/PostConfigureIdentityServerOptions.cs @@ -0,0 +1,40 @@ +using Duende.IdentityServer.Configuration; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; + +namespace Duende.IdentityServer.AspNetIdentity; + +/// +/// Identity server options configuration +/// +public class UseAspNetIdentityCookieScheme : IPostConfigureOptions +{ + private readonly IOptions _authOptions; + + /// + /// ctor + /// + /// + public UseAspNetIdentityCookieScheme(IOptions authOptions) + { + _authOptions = authOptions; + } + + /// + public void PostConfigure(string name, IdentityServerOptions options) + { + // If we are using ASP.NET Identity and the dynamic providers don't have a + // sign out scheme set, then we need the dynamic providers to use ASP.NET + // Identity's cookie at sign out time. If the sign out scheme is explicitly + // set, then we don't override that though. + + if (DefaultAuthSchemeIsAspNetIdentity() && + !options.DynamicProviders.SignOutSchemeSetExplicitly) + { + options.DynamicProviders.SignOutScheme = IdentityConstants.ApplicationScheme; + } + + bool DefaultAuthSchemeIsAspNetIdentity() => + _authOptions.Value.DefaultAuthenticateScheme == IdentityConstants.ApplicationScheme; + } +} diff --git a/src/IdentityServer/Configuration/DependencyInjection/Options/DynamicProviderOptions.cs b/src/IdentityServer/Configuration/DependencyInjection/Options/DynamicProviderOptions.cs index f73d88749..3739453e2 100644 --- a/src/IdentityServer/Configuration/DependencyInjection/Options/DynamicProviderOptions.cs +++ b/src/IdentityServer/Configuration/DependencyInjection/Options/DynamicProviderOptions.cs @@ -31,7 +31,24 @@ public class DynamicProviderOptions /// /// Scheme for signout. Defaults to the constant IdentityServerConstants.DefaultCookieAuthenticationScheme. /// - public string SignOutScheme { get; set; } = IdentityServerConstants.DefaultCookieAuthenticationScheme; + public string SignOutScheme + { + get + { + return _signOutScheme ?? IdentityServerConstants.DefaultCookieAuthenticationScheme; + } + set + { + _signOutScheme = value; + } + } + + private string? _signOutScheme; + + /// + /// Gets a value indicating if the SignOutScheme was set explicitly, either by application logic or by options binding. + /// + public bool SignOutSchemeSetExplicitly { get => _signOutScheme != null; } /// /// Registers a provider configuration model and authentication handler for the protocol type being used.