mirror of
https://github.com/DuendeSoftware/products
synced 2026-05-24 09:28:24 +00:00
Do not enable SAML by default, but provide mechnism to opt-in
This commit is contained in:
parent
64bda6c985
commit
ca9e3a360f
14 changed files with 239 additions and 101 deletions
|
|
@ -17,12 +17,6 @@ using Duende.IdentityServer.Hosting.DynamicProviders;
|
|||
using Duende.IdentityServer.Hosting.FederatedSignOut;
|
||||
using Duende.IdentityServer.Internal;
|
||||
using Duende.IdentityServer.Internal.Saml;
|
||||
using Duende.IdentityServer.Internal.Saml.Infrastructure;
|
||||
using Duende.IdentityServer.Internal.Saml.Metadata;
|
||||
using Duende.IdentityServer.Internal.Saml.SingleLogout;
|
||||
using Duende.IdentityServer.Internal.Saml.SingleLogout.Models;
|
||||
using Duende.IdentityServer.Internal.Saml.SingleSignin;
|
||||
using Duende.IdentityServer.Internal.Saml.SingleSignin.Models;
|
||||
using Duende.IdentityServer.Licensing;
|
||||
using Duende.IdentityServer.Licensing.V2;
|
||||
using Duende.IdentityServer.Licensing.V2.Diagnostics;
|
||||
|
|
@ -135,14 +129,6 @@ public static class IdentityServerBuilderExtensionsCore
|
|||
builder.AddEndpoint<TokenEndpoint>(EndpointNames.Token, ProtocolRoutePaths.Token.EnsureLeadingSlash());
|
||||
builder.AddEndpoint<UserInfoEndpoint>(EndpointNames.UserInfo, ProtocolRoutePaths.UserInfo.EnsureLeadingSlash());
|
||||
|
||||
// SAML 2.0 endpoints
|
||||
builder.AddEndpoint<SamlMetaDataEndpoint>(EndpointNames.SamlMetadata, ProtocolRoutePaths.SamlMetadata.EnsureLeadingSlash());
|
||||
builder.AddEndpoint<SamlSigninEndpoint>(EndpointNames.SamlSignin, ProtocolRoutePaths.SamlSignin.EnsureLeadingSlash());
|
||||
builder.AddEndpoint<SamlSigninCallbackEndpoint>(EndpointNames.SamlSigninCallback, ProtocolRoutePaths.SamlSigninCallback.EnsureLeadingSlash());
|
||||
builder.AddEndpoint<SamlIdpInitiatedEndpoint>(EndpointNames.SamlIdpInitiated, ProtocolRoutePaths.SamlIdpInitiated.EnsureLeadingSlash());
|
||||
builder.AddEndpoint<SamlSingleLogoutEndpoint>(EndpointNames.SamlLogout, ProtocolRoutePaths.SamlLogout.EnsureLeadingSlash());
|
||||
builder.AddEndpoint<SamlSingleLogoutCallbackEndpoint>(EndpointNames.SamlLogoutCallback, ProtocolRoutePaths.SamlLogoutCallback.EnsureLeadingSlash());
|
||||
|
||||
builder.AddHttpWriter<AuthorizeInteractionPageResult, AuthorizeInteractionPageHttpWriter>();
|
||||
builder.AddHttpWriter<AuthorizeResult, AuthorizeHttpWriter>();
|
||||
builder.AddHttpWriter<BackchannelAuthenticationResult, BackchannelAuthenticationHttpWriter>();
|
||||
|
|
@ -166,67 +152,6 @@ public static class IdentityServerBuilderExtensionsCore
|
|||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds SAML 2.0 protocol services.
|
||||
/// </summary>
|
||||
/// <param name="builder">The builder.</param>
|
||||
/// <returns></returns>
|
||||
public static IIdentityServerBuilder AddSamlServices(this IIdentityServerBuilder builder)
|
||||
{
|
||||
// Serializers (Transient)
|
||||
builder.Services.AddTransient<ISamlResultSerializer<SamlErrorResponse>, SamlErrorResponseXmlSerializer>();
|
||||
builder.Services.AddTransient<ISamlResultSerializer<SamlResponse>, SamlResponse.Serializer>();
|
||||
builder.Services.AddTransient<ISamlResultSerializer<LogoutResponse>, LogoutResponse.Serializer>();
|
||||
|
||||
// HTTP response writers
|
||||
builder.AddHttpWriter<SamlErrorResponse, SamlErrorResponse.ResponseWriter>();
|
||||
builder.AddHttpWriter<SamlResponse, SamlResponse.ResponseWriter>();
|
||||
builder.AddHttpWriter<LogoutResponse, LogoutResponse.ResponseWriter>();
|
||||
|
||||
// Processors (Scoped)
|
||||
builder.Services.AddScoped<SamlSigninRequestProcessor>();
|
||||
builder.Services.AddScoped<SamlSigninCallbackRequestProcessor>();
|
||||
builder.Services.AddScoped<SamlIdpInitiatedRequestProcessor>();
|
||||
builder.Services.AddScoped<SamlLogoutRequestProcessor>();
|
||||
builder.Services.AddScoped<SamlLogoutCallbackProcessor>();
|
||||
|
||||
// Builders (Scoped)
|
||||
builder.Services.AddScoped<SamlResponseBuilder>();
|
||||
builder.Services.AddScoped<LogoutResponseBuilder>();
|
||||
builder.Services.AddScoped<SamlFrontChannelLogoutRequestBuilder>();
|
||||
|
||||
// Parsers / Extractors (Scoped)
|
||||
builder.Services.AddScoped<AuthNRequestParser>();
|
||||
builder.Services.AddScoped<LogoutRequestParser>();
|
||||
builder.Services.AddScoped<SamlSigninRequestExtractor>();
|
||||
builder.Services.AddScoped<SamlLogoutRequestExtractor>();
|
||||
|
||||
// Infrastructure (Scoped)
|
||||
builder.Services.AddScoped<SamlUrlBuilder>();
|
||||
builder.Services.AddScoped<SamlClaimsService>();
|
||||
builder.Services.AddScoped<SamlNameIdGenerator>();
|
||||
builder.Services.AddScoped<SamlResponseSigner>();
|
||||
builder.Services.AddScoped<SamlProtocolMessageSigner>();
|
||||
builder.Services.AddScoped<SamlAssertionEncryptor>();
|
||||
builder.Services.AddScoped<SamlRequestValidator>();
|
||||
builder.Services.TryAddScoped(typeof(SamlRequestSignatureValidator<,>));
|
||||
|
||||
// Interface → Implementation (TryAddScoped for extensibility)
|
||||
builder.Services.TryAddScoped<ISamlSigninInteractionResponseGenerator, DefaultSamlSigninInteractionResponseGenerator>();
|
||||
builder.Services.TryAddScoped<ISamlSigningService, SamlSigningService>();
|
||||
builder.Services.TryAddScoped<ISamlLogoutNotificationService, SamlLogoutNotificationService>();
|
||||
builder.Services.TryAddScoped<ISamlInteractionService, DefaultSamlInteractionService>();
|
||||
|
||||
// State management (Singleton)
|
||||
builder.Services.TryAddSingleton<SamlSigninStateIdCookie>();
|
||||
builder.Services.TryAddSingleton<ISamlSigninStateStore, DistributedCacheSamlSigninStateStore>();
|
||||
|
||||
// Default no-op service provider store (can be overridden by user)
|
||||
builder.Services.TryAddTransient<ISamlServiceProviderStore, InMemorySamlServiceProviderStore>();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an endpoint.
|
||||
/// </summary>
|
||||
|
|
@ -287,6 +212,12 @@ public static class IdentityServerBuilderExtensionsCore
|
|||
|
||||
builder.Services.TryAddTransient<IBackchannelAuthenticationUserValidator, NopBackchannelAuthenticationUserValidator>();
|
||||
|
||||
// Register no-op SAML services for services used in logout paths
|
||||
// These are replaced by actual implementations in AddSaml and ISamlServiceProviderStore
|
||||
// can be replaced with a call to AddSamlServiceProviderStore
|
||||
builder.Services.TryAddTransient<ISamlServiceProviderStore, EmptySamlServiceProviderStore>();
|
||||
builder.Services.TryAddScoped<ISamlLogoutNotificationService, NopSamlLogoutNotificationService>();
|
||||
|
||||
builder.Services.TryAddSingleton(typeof(IConcurrencyLock<>), typeof(DefaultConcurrencyLock<>));
|
||||
|
||||
builder.Services.TryAddTransient<IClientStore, EmptyClientStore>();
|
||||
|
|
|
|||
|
|
@ -190,4 +190,17 @@ public static class IdentityServerBuilderExtensionsInMemory
|
|||
builder.Services.TryAddSingleton<IPushedAuthorizationRequestStore, InMemoryPushedAuthorizationRequestStore>();
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the in-memory SAML service provider store.
|
||||
/// </summary>
|
||||
/// <param name="builder">The builder.</param>
|
||||
/// <param name="serviceProviders">The SAML service providers.</param>
|
||||
/// <returns></returns>
|
||||
public static IIdentityServerBuilder AddInMemorySamlServiceProviders(this IIdentityServerBuilder builder, IEnumerable<SamlServiceProvider> serviceProviders)
|
||||
{
|
||||
builder.Services.AddSingleton(serviceProviders);
|
||||
builder.AddSamlServiceProviderStore<InMemorySamlServiceProviderStore>();
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,134 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using Duende.IdentityServer.Configuration;
|
||||
using Duende.IdentityServer.Extensions;
|
||||
using Duende.IdentityServer.Internal.Saml;
|
||||
using Duende.IdentityServer.Internal.Saml.Infrastructure;
|
||||
using Duende.IdentityServer.Internal.Saml.Metadata;
|
||||
using Duende.IdentityServer.Internal.Saml.SingleLogout;
|
||||
using Duende.IdentityServer.Internal.Saml.SingleLogout.Models;
|
||||
using Duende.IdentityServer.Internal.Saml.SingleSignin;
|
||||
using Duende.IdentityServer.Internal.Saml.SingleSignin.Models;
|
||||
using Duende.IdentityServer.Saml;
|
||||
using Duende.IdentityServer.Stores;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using static Duende.IdentityServer.IdentityServerConstants;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
/// <summary>
|
||||
/// Builder extension methods for opting in to SAML 2.0 support.
|
||||
/// </summary>
|
||||
public static class IdentityServerBuilderExtensionsSaml
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds SAML 2.0 support to IdentityServer.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Registers all SAML services and endpoints, and enables the SAML endpoints
|
||||
/// in <see cref="EndpointsOptions"/>. The IdP-initiated SSO endpoint is not
|
||||
/// enabled by default; set <see cref="EndpointsOptions.EnableSamlIdpInitiatedEndpoint"/>
|
||||
/// to <c>true</c> explicitly if you need it.
|
||||
/// </remarks>
|
||||
/// <param name="builder">The builder.</param>
|
||||
/// <returns></returns>
|
||||
public static IIdentityServerBuilder AddSaml(this IIdentityServerBuilder builder)
|
||||
{
|
||||
builder.AddSamlServices();
|
||||
|
||||
builder.Services.Configure<IdentityServerOptions>(options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlMetadataEndpoint = true;
|
||||
options.Endpoints.EnableSamlSigninEndpoint = true;
|
||||
options.Endpoints.EnableSamlSigninCallbackEndpoint = true;
|
||||
options.Endpoints.EnableSamlLogoutEndpoint = true;
|
||||
options.Endpoints.EnableSamlLogoutCallbackEndpoint = true;
|
||||
// EnableSamlIdpInitiatedEndpoint intentionally left false — requires explicit opt-in.
|
||||
});
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds SAML 2.0 protocol services.
|
||||
/// </summary>
|
||||
/// <param name="builder">The builder.</param>
|
||||
/// <returns></returns>
|
||||
private static IIdentityServerBuilder AddSamlServices(this IIdentityServerBuilder builder)
|
||||
{
|
||||
// SAML 2.0 endpoints
|
||||
builder.AddEndpoint<SamlMetaDataEndpoint>(EndpointNames.SamlMetadata, ProtocolRoutePaths.SamlMetadata.EnsureLeadingSlash());
|
||||
builder.AddEndpoint<SamlSigninEndpoint>(EndpointNames.SamlSignin, ProtocolRoutePaths.SamlSignin.EnsureLeadingSlash());
|
||||
builder.AddEndpoint<SamlSigninCallbackEndpoint>(EndpointNames.SamlSigninCallback, ProtocolRoutePaths.SamlSigninCallback.EnsureLeadingSlash());
|
||||
builder.AddEndpoint<SamlIdpInitiatedEndpoint>(EndpointNames.SamlIdpInitiated, ProtocolRoutePaths.SamlIdpInitiated.EnsureLeadingSlash());
|
||||
builder.AddEndpoint<SamlSingleLogoutEndpoint>(EndpointNames.SamlLogout, ProtocolRoutePaths.SamlLogout.EnsureLeadingSlash());
|
||||
builder.AddEndpoint<SamlSingleLogoutCallbackEndpoint>(EndpointNames.SamlLogoutCallback, ProtocolRoutePaths.SamlLogoutCallback.EnsureLeadingSlash());
|
||||
|
||||
// Serializers (Transient)
|
||||
builder.Services.AddTransient<ISamlResultSerializer<SamlErrorResponse>, SamlErrorResponseXmlSerializer>();
|
||||
builder.Services.AddTransient<ISamlResultSerializer<SamlResponse>, SamlResponse.Serializer>();
|
||||
builder.Services.AddTransient<ISamlResultSerializer<LogoutResponse>, LogoutResponse.Serializer>();
|
||||
|
||||
// HTTP response writers
|
||||
builder.AddHttpWriter<SamlErrorResponse, SamlErrorResponse.ResponseWriter>();
|
||||
builder.AddHttpWriter<SamlResponse, SamlResponse.ResponseWriter>();
|
||||
builder.AddHttpWriter<LogoutResponse, LogoutResponse.ResponseWriter>();
|
||||
|
||||
// Processors (Scoped)
|
||||
builder.Services.AddScoped<SamlSigninRequestProcessor>();
|
||||
builder.Services.AddScoped<SamlSigninCallbackRequestProcessor>();
|
||||
builder.Services.AddScoped<SamlIdpInitiatedRequestProcessor>();
|
||||
builder.Services.AddScoped<SamlLogoutRequestProcessor>();
|
||||
builder.Services.AddScoped<SamlLogoutCallbackProcessor>();
|
||||
|
||||
// Builders (Scoped)
|
||||
builder.Services.AddScoped<SamlResponseBuilder>();
|
||||
builder.Services.AddScoped<LogoutResponseBuilder>();
|
||||
builder.Services.AddScoped<SamlFrontChannelLogoutRequestBuilder>();
|
||||
|
||||
// Parsers / Extractors (Scoped)
|
||||
builder.Services.AddScoped<AuthNRequestParser>();
|
||||
builder.Services.AddScoped<LogoutRequestParser>();
|
||||
builder.Services.AddScoped<SamlSigninRequestExtractor>();
|
||||
builder.Services.AddScoped<SamlLogoutRequestExtractor>();
|
||||
|
||||
// Infrastructure (Scoped)
|
||||
builder.Services.AddScoped<SamlUrlBuilder>();
|
||||
builder.Services.AddScoped<SamlClaimsService>();
|
||||
builder.Services.AddScoped<SamlNameIdGenerator>();
|
||||
builder.Services.AddScoped<SamlResponseSigner>();
|
||||
builder.Services.AddScoped<SamlProtocolMessageSigner>();
|
||||
builder.Services.AddScoped<SamlAssertionEncryptor>();
|
||||
builder.Services.AddScoped<SamlRequestValidator>();
|
||||
builder.Services.TryAddScoped(typeof(SamlRequestSignatureValidator<,>));
|
||||
|
||||
// Interface → Implementation (TryAddScoped for extensibility)
|
||||
builder.Services.TryAddScoped<ISamlSigninInteractionResponseGenerator, DefaultSamlSigninInteractionResponseGenerator>();
|
||||
builder.Services.TryAddScoped<ISamlSigningService, SamlSigningService>();
|
||||
// Replace the no-op registered by AddCoreServices with the real implementation.
|
||||
builder.Services.Replace(ServiceDescriptor.Scoped<ISamlLogoutNotificationService, SamlLogoutNotificationService>());
|
||||
builder.Services.TryAddScoped<ISamlInteractionService, DefaultSamlInteractionService>();
|
||||
|
||||
// State management (Singleton)
|
||||
builder.Services.TryAddSingleton<SamlSigninStateIdCookie>();
|
||||
builder.Services.TryAddSingleton<ISamlSigninStateStore, DistributedCacheSamlSigninStateStore>();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a custom SAML service provider store.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the <see cref="ISamlServiceProviderStore"/> implementation.</typeparam>
|
||||
/// <param name="builder">The builder.</param>
|
||||
/// <returns></returns>
|
||||
public static IIdentityServerBuilder AddSamlServiceProviderStore<T>(this IIdentityServerBuilder builder)
|
||||
where T : class, ISamlServiceProviderStore
|
||||
{
|
||||
builder.Services.AddTransient<ISamlServiceProviderStore, T>();
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
|
@ -37,7 +37,6 @@ public static class IdentityServerServiceCollectionExtensions
|
|||
.AddCookieAuthentication()
|
||||
.AddCoreServices()
|
||||
.AddDefaultEndpoints()
|
||||
.AddSamlServices()
|
||||
.AddPluggableServices()
|
||||
.AddKeyManagement()
|
||||
.AddDynamicProvidersCore()
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ public class EndpointsOptions
|
|||
/// <value>
|
||||
/// <c>true</c> if the SAML metadata endpoint is enabled; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool EnableSamlMetadataEndpoint { get; set; } = true;
|
||||
public bool EnableSamlMetadataEndpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the SAML sign-in (SSO) endpoint is enabled.
|
||||
|
|
@ -126,7 +126,7 @@ public class EndpointsOptions
|
|||
/// <value>
|
||||
/// <c>true</c> if the SAML sign-in endpoint is enabled; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool EnableSamlSigninEndpoint { get; set; } = true;
|
||||
public bool EnableSamlSigninEndpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the SAML sign-in callback endpoint is enabled.
|
||||
|
|
@ -134,7 +134,7 @@ public class EndpointsOptions
|
|||
/// <value>
|
||||
/// <c>true</c> if the SAML sign-in callback endpoint is enabled; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool EnableSamlSigninCallbackEndpoint { get; set; } = true;
|
||||
public bool EnableSamlSigninCallbackEndpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the SAML IdP-initiated SSO endpoint is enabled.
|
||||
|
|
@ -142,7 +142,7 @@ public class EndpointsOptions
|
|||
/// <value>
|
||||
/// <c>true</c> if the SAML IdP-initiated endpoint is enabled; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool EnableSamlIdpInitiatedEndpoint { get; set; } = true;
|
||||
public bool EnableSamlIdpInitiatedEndpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the SAML Single Logout (SLO) endpoint is enabled.
|
||||
|
|
@ -150,7 +150,7 @@ public class EndpointsOptions
|
|||
/// <value>
|
||||
/// <c>true</c> if the SAML logout endpoint is enabled; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool EnableSamlLogoutEndpoint { get; set; } = true;
|
||||
public bool EnableSamlLogoutEndpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the SAML Single Logout callback endpoint is enabled.
|
||||
|
|
@ -158,5 +158,5 @@ public class EndpointsOptions
|
|||
/// <value>
|
||||
/// <c>true</c> if the SAML logout callback endpoint is enabled; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool EnableSamlLogoutCallbackEndpoint { get; set; } = true;
|
||||
public bool EnableSamlLogoutCallbackEndpoint { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
using Duende.IdentityServer.Models;
|
||||
using Duende.IdentityServer.Stores;
|
||||
|
||||
namespace Duende.IdentityServer.Internal.Saml;
|
||||
|
||||
internal class EmptySamlServiceProviderStore : ISamlServiceProviderStore
|
||||
{
|
||||
public Task<SamlServiceProvider> FindByEntityIdAsync(string entityId) => Task.FromResult<SamlServiceProvider>(null);
|
||||
}
|
||||
|
|
@ -2,8 +2,6 @@
|
|||
// See LICENSE in the project root for license information.
|
||||
|
||||
#nullable enable
|
||||
using Duende.IdentityServer.Saml.Models;
|
||||
|
||||
namespace Duende.IdentityServer.Internal.Saml.Infrastructure;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using Duende.IdentityServer.Models;
|
||||
using Duende.IdentityServer.Saml;
|
||||
|
||||
namespace Duende.IdentityServer.Internal.Saml;
|
||||
|
||||
internal class NopSamlLogoutNotificationService : ISamlLogoutNotificationService
|
||||
{
|
||||
public Task<IEnumerable<ISamlFrontChannelLogout>> GetSamlFrontChannelLogoutsAsync(LogoutNotificationContext context) =>
|
||||
Task.FromResult(Enumerable.Empty<ISamlFrontChannelLogout>());
|
||||
}
|
||||
|
|
@ -11,7 +11,6 @@ using Duende.IdentityServer.Internal.Saml.SingleLogout.Models;
|
|||
using Duende.IdentityServer.Internal.Saml.SingleSignin.Models;
|
||||
using Duende.IdentityServer.Models;
|
||||
using Duende.IdentityServer.Saml;
|
||||
using Duende.IdentityServer.Saml.Models;
|
||||
using LogoutRequest = Duende.IdentityServer.Internal.Saml.SingleLogout.Models.LogoutRequest;
|
||||
|
||||
namespace Duende.IdentityServer.Internal.Saml.SingleLogout;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ using Duende.IdentityServer.Hosting.DynamicProviders;
|
|||
using Duende.IdentityServer.Internal;
|
||||
using Duende.IdentityServer.Internal.Saml;
|
||||
using Duende.IdentityServer.Internal.Saml.SingleLogout;
|
||||
using Duende.IdentityServer.Internal.Saml.SingleSignin;
|
||||
using Duende.IdentityServer.ResponseHandling;
|
||||
using Duende.IdentityServer.Saml;
|
||||
using Duende.IdentityServer.Services;
|
||||
|
|
@ -60,9 +59,9 @@ internal class RegisteredImplementationsDiagnosticEntry(ServiceCollectionAccesso
|
|||
"SAML", [
|
||||
new(typeof(ISamlClaimsMapper), []),
|
||||
new(typeof(ISamlFrontChannelLogout), [typeof(SamlHttpPostFrontChannelLogout), typeof(SamlHttpRedirectFrontChannelLogout)]),
|
||||
new(typeof(ISamlInteractionService),[typeof(DefaultSamlInteractionService)]),
|
||||
new(typeof(ISamlLogoutNotificationService), [typeof(SamlLogoutNotificationService)]),
|
||||
new(typeof(ISamlSigninInteractionResponseGenerator),[typeof(DefaultSamlSigninInteractionResponseGenerator)]),
|
||||
new(typeof(ISamlInteractionService),[]),
|
||||
new(typeof(ISamlLogoutNotificationService), [typeof(NopSamlLogoutNotificationService)]),
|
||||
new(typeof(ISamlSigninInteractionResponseGenerator),[]),
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -96,7 +95,6 @@ internal class RegisteredImplementationsDiagnosticEntry(ServiceCollectionAccesso
|
|||
new(typeof(IRefreshTokenService), [typeof(DefaultRefreshTokenService)]),
|
||||
new(typeof(IReplayCache), [typeof(DefaultReplayCache)]),
|
||||
new(typeof(IReturnUrlParser), [typeof(OidcReturnUrlParser)]),
|
||||
new(typeof(ISamlServiceProviderStore), [typeof(InMemorySamlServiceProviderStore)]),
|
||||
new(typeof(IServerUrls), [typeof(DefaultServerUrls)]),
|
||||
new(typeof(ISessionCoordinationService), [typeof(DefaultSessionCoordinationService)]),
|
||||
new(typeof(ISessionManagementService), []),
|
||||
|
|
@ -126,6 +124,7 @@ internal class RegisteredImplementationsDiagnosticEntry(ServiceCollectionAccesso
|
|||
new(typeof(IReferenceTokenStore), [typeof(DefaultReferenceTokenStore)]),
|
||||
new(typeof(IRefreshTokenStore), [typeof(DefaultRefreshTokenStore)]),
|
||||
new(typeof(IResourceStore), [typeof(EmptyResourceStore)]),
|
||||
new(typeof(ISamlServiceProviderStore), [typeof(EmptySamlServiceProviderStore)]),
|
||||
new(typeof(IServerSideSessionsMarker), []),
|
||||
new(typeof(IServerSideSessionStore),[]),
|
||||
new(typeof(IServerSideTicketStore),[]),
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ using System.Security.Cryptography;
|
|||
using System.Security.Cryptography.X509Certificates;
|
||||
using Duende.IdentityModel;
|
||||
using Duende.IdentityServer.Models;
|
||||
using static Duende.IdentityServer.IntegrationTests.Endpoints.Saml.SamlTestHelpers;
|
||||
using Duende.IdentityServer.Saml.Models;
|
||||
using static Duende.IdentityServer.IntegrationTests.Endpoints.Saml.SamlTestHelpers;
|
||||
|
||||
namespace Duende.IdentityServer.IntegrationTests.Endpoints.Saml;
|
||||
|
||||
|
|
|
|||
|
|
@ -121,9 +121,6 @@ internal class SamlFixture : IAsyncLifetime
|
|||
// Configure SAML options
|
||||
services.Configure(ConfigureSamlOptions);
|
||||
|
||||
// Register in-memory SAML service provider store with our service providers
|
||||
services.AddSingleton<ISamlServiceProviderStore>(new InMemorySamlServiceProviderStore(_serviceProviders));
|
||||
|
||||
// Replace the developer signing credential with our X509 certificate
|
||||
// Remove the ISigningCredentialStore registration added by AddDeveloperSigningCredential
|
||||
var signingCredentialDescriptor = services.FirstOrDefault(d => d.ServiceType == typeof(ISigningCredentialStore));
|
||||
|
|
@ -136,7 +133,8 @@ internal class SamlFixture : IAsyncLifetime
|
|||
services.AddIdentityServerBuilder()
|
||||
.AddSigningCredential(selfSignedCertificate)
|
||||
.AddProfileService<DefaultProfileService>()
|
||||
.AddSamlServices();
|
||||
.AddSaml()
|
||||
.AddInMemorySamlServiceProviders(_serviceProviders);
|
||||
|
||||
ConfigureServices(services);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ public class SamlIdpInitiatedEndpointTests
|
|||
var sp = Build.SamlServiceProvider();
|
||||
sp.AllowIdpInitiated = true;
|
||||
Fixture.ServiceProviders.Add(sp);
|
||||
Fixture.ConfigureIdentityServerOptions = options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlIdpInitiatedEndpoint = true;
|
||||
};
|
||||
await Fixture.InitializeAsync();
|
||||
|
||||
Fixture.UserToSignIn =
|
||||
|
|
@ -55,6 +59,10 @@ public class SamlIdpInitiatedEndpointTests
|
|||
var sp = Build.SamlServiceProvider();
|
||||
sp.AllowIdpInitiated = true;
|
||||
Fixture.ServiceProviders.Add(sp);
|
||||
Fixture.ConfigureIdentityServerOptions = options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlIdpInitiatedEndpoint = true;
|
||||
};
|
||||
await Fixture.InitializeAsync();
|
||||
|
||||
Fixture.UserToSignIn =
|
||||
|
|
@ -87,6 +95,10 @@ public class SamlIdpInitiatedEndpointTests
|
|||
var sp = Build.SamlServiceProvider();
|
||||
sp.AllowIdpInitiated = true;
|
||||
Fixture.ServiceProviders.Add(sp);
|
||||
Fixture.ConfigureIdentityServerOptions = options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlIdpInitiatedEndpoint = true;
|
||||
};
|
||||
await Fixture.InitializeAsync();
|
||||
|
||||
// Act
|
||||
|
|
@ -106,6 +118,10 @@ public class SamlIdpInitiatedEndpointTests
|
|||
{
|
||||
// Arrange
|
||||
Fixture.ServiceProviders.Add(Build.SamlServiceProvider());
|
||||
Fixture.ConfigureIdentityServerOptions = options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlIdpInitiatedEndpoint = true;
|
||||
};
|
||||
await Fixture.InitializeAsync();
|
||||
|
||||
// Act
|
||||
|
|
@ -130,6 +146,10 @@ public class SamlIdpInitiatedEndpointTests
|
|||
sp.Enabled = false;
|
||||
sp.AllowIdpInitiated = true;
|
||||
Fixture.ServiceProviders.Add(sp);
|
||||
Fixture.ConfigureIdentityServerOptions = options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlIdpInitiatedEndpoint = true;
|
||||
};
|
||||
await Fixture.InitializeAsync();
|
||||
|
||||
// Act
|
||||
|
|
@ -152,6 +172,10 @@ public class SamlIdpInitiatedEndpointTests
|
|||
var sp = Build.SamlServiceProvider();
|
||||
sp.AllowIdpInitiated = false;
|
||||
Fixture.ServiceProviders.Add(sp);
|
||||
Fixture.ConfigureIdentityServerOptions = options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlIdpInitiatedEndpoint = true;
|
||||
};
|
||||
await Fixture.InitializeAsync();
|
||||
|
||||
// Act
|
||||
|
|
@ -178,6 +202,10 @@ public class SamlIdpInitiatedEndpointTests
|
|||
var sp = Build.SamlServiceProvider();
|
||||
sp.AllowIdpInitiated = true;
|
||||
Fixture.ServiceProviders.Add(sp);
|
||||
Fixture.ConfigureIdentityServerOptions = options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlIdpInitiatedEndpoint = true;
|
||||
};
|
||||
await Fixture.InitializeAsync();
|
||||
|
||||
// Act
|
||||
|
|
@ -202,6 +230,10 @@ public class SamlIdpInitiatedEndpointTests
|
|||
sp.AllowIdpInitiated = true;
|
||||
sp.AssertionConsumerServiceUrls = Array.Empty<Uri>();
|
||||
Fixture.ServiceProviders.Add(sp);
|
||||
Fixture.ConfigureIdentityServerOptions = options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlIdpInitiatedEndpoint = true;
|
||||
};
|
||||
await Fixture.InitializeAsync();
|
||||
|
||||
// Act
|
||||
|
|
@ -227,6 +259,10 @@ public class SamlIdpInitiatedEndpointTests
|
|||
sp.AllowIdpInitiated = true;
|
||||
sp.AssertionConsumerServiceUrls = [firstAcsUrl, secondAcsUrl];
|
||||
Fixture.ServiceProviders.Add(sp);
|
||||
Fixture.ConfigureIdentityServerOptions = options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlIdpInitiatedEndpoint = true;
|
||||
};
|
||||
await Fixture.InitializeAsync();
|
||||
|
||||
Fixture.UserToSignIn =
|
||||
|
|
@ -257,6 +293,10 @@ public class SamlIdpInitiatedEndpointTests
|
|||
var sp = Build.SamlServiceProvider();
|
||||
sp.AllowIdpInitiated = true;
|
||||
Fixture.ServiceProviders.Add(sp);
|
||||
Fixture.ConfigureIdentityServerOptions = options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlIdpInitiatedEndpoint = true;
|
||||
};
|
||||
await Fixture.InitializeAsync();
|
||||
|
||||
Fixture.UserToSignIn =
|
||||
|
|
@ -332,6 +372,10 @@ public class SamlIdpInitiatedEndpointTests
|
|||
public async Task missing_sp_entity_id_parameter_returns_bad_request()
|
||||
{
|
||||
Fixture.ServiceProviders.Add(Build.SamlServiceProvider());
|
||||
Fixture.ConfigureIdentityServerOptions = options =>
|
||||
{
|
||||
options.Endpoints.EnableSamlIdpInitiatedEndpoint = true;
|
||||
};
|
||||
await Fixture.InitializeAsync();
|
||||
|
||||
var result = await Fixture.Client.GetAsync("/saml/idp-initiated", CancellationToken.None);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ using Duende.IdentityModel;
|
|||
using Duende.IdentityServer.IntegrationTests.Common;
|
||||
using Duende.IdentityServer.IntegrationTests.TestFramework;
|
||||
using Duende.IdentityServer.Models;
|
||||
using Duende.IdentityServer.Stores;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
|
@ -95,10 +94,6 @@ internal class SustainSysSamlTestFixture(ITestOutputHelper output) : IAsyncLifet
|
|||
services.AddSingleton<TimeProvider>(fakeTimeProvider);
|
||||
services.AddSingleton<IDistributedCache>(sp => new FakeDistributedCache(sp.GetRequiredService<TimeProvider>()));
|
||||
|
||||
// Register the mutable service provider list before AddSamlServices
|
||||
// so TryAdd in AddSamlServices won't overwrite our registration
|
||||
services.AddSingleton<ISamlServiceProviderStore>(new InMemorySamlServiceProviderStore(_serviceProviders));
|
||||
|
||||
services.AddIdentityServer(options =>
|
||||
{
|
||||
options.UserInteraction.LoginUrl = "/account/login";
|
||||
|
|
@ -107,7 +102,8 @@ internal class SustainSysSamlTestFixture(ITestOutputHelper output) : IAsyncLifet
|
|||
options.KeyManagement.Enabled = false;
|
||||
})
|
||||
.AddSigningCredential(selfSignedCertificate)
|
||||
.AddSamlServices();
|
||||
.AddSaml()
|
||||
.AddInMemorySamlServiceProviders(_serviceProviders);
|
||||
},
|
||||
app =>
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue