Skip to content

ISAMLConfigurationResolver

The ISAMLConfigurationResolver interface provides an alternative mechanism for supplying SAML configuration. Rather than configuring SAML at application startup, the resolver returns SAML configuration on demand as it is requested. This approach is intended for highly dynamic, multi-tenant, or frequently changing configurations.

The following code specifies a SAML configuration resolver.

SAMLController.ConfigurationResolver = new CustomConfigurationResolver();

As a convenience, the AbstractSAMLConfigurationResolver base class may be extended to avoid implementing interface methods that are not required.

The configurationName parameter identifies the SAML configuration being requested and may be used to support multiple logical configurations or tenants.

Local Service Provider Example

The following is an example of implementing ISAMLConfigurationResolver as the service provider.

In practice, these values are typically retrieved from a database or other external configuration store rather than being hard-coded.

using ComponentSpace.SAML2.Configuration.Resolver;

public class CustomConfigurationResolver : AbstractSAMLConfigurationResolver
{
    /// <summary>
    /// Gets the <c>LocalServiceProviderConfiguration</c>.
    /// </summary>
    /// <param name="configurationName">The configuration name or <c>null</c> if none.</param>
    /// <returns>The local service provider configuration.</returns>
    /// <exception cref="SAMLException">
    /// Thrown when the local service provider configuration cannot be found.
    /// </exception>
    public override LocalServiceProviderConfiguration GetLocalServiceProviderConfiguration(string configurationName)
    {
        return new LocalServiceProviderConfiguration()
        {
            Name = "https://ExampleServiceProvider",
            AssertionConsumerServiceUrl = "~/SAML/AssertionConsumerService.aspx",
            LocalCertificates = new List<CertificateConfiguration>()
            {
                new CertificateConfiguration()
                {
                    FileName = @"certificates\sp.pfx",
                    Password = "password"
                }
            }
        };
    }

    /// <summary>
    /// Gets the <c>PartnerIdentityProviderConfiguration</c> given the partner name.
    /// </summary>
    /// <param name="configurationName">The configuration name or <c>null</c> if none.</param>
    /// <param name="partnerName">The partner name.</param>
    /// <returns>The partner identity provider configuration.</returns>
    /// <exception cref="SAMLException">
    /// Thrown when the partner identity provider configuration cannot be found.
    /// </exception>
    public override PartnerIdentityProviderConfiguration GetPartnerIdentityProviderConfiguration(string configurationName, string partnerName)
    {
        switch (partnerName)
        {
            case "https://ExampleIdentityProvider":
                return new PartnerIdentityProviderConfiguration()
                {
                    Name = "https://ExampleIdentityProvider",
                    SingleSignOnServiceUrl = "https://localhost:44390/SAML/SSOService.aspx",
                    SingleLogoutServiceUrl = "https://localhost:44390/SAML/SLOService.aspx",
                    PartnerCertificates = new List<CertificateConfiguration>()
                    {
                        new CertificateConfiguration()
                        {
                            FileName = @"certificates\idp.cer",
                        }
                    }
                };

            default:
                throw new SAMLConfigurationException("The partner identity provider is unknown.");
        }
    }
}

Local Identity Provider Example

The following is an example of implementing ISAMLConfigurationResolver as the identity provider.

In practice, these values are typically retrieved from a database or other external configuration store rather than being hard-coded.

using ComponentSpace.SAML2.Configuration.Resolver;

public class CustomConfigurationResolver : AbstractSAMLConfigurationResolver
{
    /// <summary>
    /// Gets the <c>LocalIdentityProviderConfiguration</c>.
    /// </summary>
    /// <param name="configurationName">The configuration name or <c>null</c> if none.</param>
    /// <returns>The local identity provider configuration.</returns>
    /// <exception cref="SAMLException">
    /// Thrown when the local identity provider configuration cannot be found.
    /// </exception>
    public override LocalIdentityProviderConfiguration GetLocalIdentityProviderConfiguration(string configurationName)
    {
        return new LocalIdentityProviderConfiguration()
        {
            Name = "https://ExampleIdentityProvider",
            LocalCertificates = new List<CertificateConfiguration>()
            {
                new CertificateConfiguration()
                {
                    FileName = @"certificates\idp.pfx",
                    Password = "password"
                }
            }
        };
    }

    /// <summary>
    /// Gets the <c>PartnerServiceProviderConfiguration</c> given the partner name.
    /// </summary>
    /// <param name="configurationName">The configuration name or <c>null</c> if none.</param>
    /// <param name="partnerName">The partner name.</param>
    /// <returns>The partner service provider configuration.</returns>
    /// <exception cref="SAMLException">
    /// Thrown when the partner service provider configuration cannot be found.
    /// </exception>
    public override PartnerServiceProviderConfiguration GetPartnerServiceProviderConfiguration(string configurationName, string partnerName)
    {
        switch (partnerName)
        {
            case "https://ExampleServiceProvider":
                return new PartnerServiceProviderConfiguration()
                {
                    Name = "https://ExampleServiceProvider",
                    AssertionConsumerServiceUrl = "https://localhost:44338/SAML/AssertionConsumerService.aspx",
                    SingleLogoutServiceUrl = "https://localhost:44338/SAML/SLOService.aspx",
                    PartnerCertificates = new List<CertificateConfiguration>()
                    {
                        new CertificateConfiguration()
                        {
                            FileName = @"certificates\sp.cer"
                        }
                    }
                };

            default:
                throw new SAMLConfigurationException("The partner service provider is unknown.");
        }
    }
}

Configuration Name Resolution

The ISAMLConfigurationNameResolver interface maps SAML message issuer names to partner configuration names.

A default implementation performs a one-to-one mapping which is appropriate for most use cases.

The following code specifies a SAML configuration name resolver.

SAMLController.ConfigurationNameResolver = 
    new CustomConfigurationNameResolver();

Regular Expression Configuration Name Resolution

RegexSAMLConfigurationNameResolver maps SAML message issuer names to partner configuration names using a regular expression.

The following code specifies the regular expression SAML configuration name resolver.

SAMLController.ConfigurationNameResolver = 
    new RegexSAMLConfigurationNameResolver();

Using the regular expression configuration name resolver, the following example SAML partner identity provider configuration matches any tenant in an Entra ID multi-tenant configuration.

The Name "https://sts.windows.net/" is used as a regular expression pattern and will match SAML message issuer names such as "https://sts.windows.net/f2f933ec-d7c9-433f-8926-d3a0732a7dcf/".

<PartnerIdentityProvider
    Name="https://sts.windows.net/"
    Description="Entra ID (Azure AD) multitenant"/>