I need to set up multiple local service providers

We have a bunch of different clients for our application. Even though we use one set of code we use the sub domain to differentiate them.
Examples: client1.test.com, client2.test.com.

Well each one of those clients can have a different IDP and in turn I think I need a different SP configuration on my machine for each one(they may have to use different keys. I was going to load them from the database. I tried loading them in the following way:
Dim samlConfiguration As New SAMLConfiguration()
For Each idp As SSOIdentityProviderModel In IDPs
samlConfiguration.AddPartnerIdentityProvider(New PartnerIdentityProviderConfiguration With {
.Name = idp.Name,
.Description = idp.Description,
.SignAuthnRequest = idp.SignAuthRequest,
.WantSAMLResponseSigned = idp.WantSAMLResponseSigned,
.WantAssertionSigned = idp.WantAssertionSigned,
.WantAssertionEncrypted = idp.WantAssertionEncrypted,
.WantLogoutResponseSigned = idp.WantLogoutResponseSigned,
.SingleSignOnServiceUrl = idp.SingleSignOnServiceUrl,
.SingleLogoutServiceUrl = idp.SingleSignOnLogoutServiceUrl,
.PartnerCertificateFile = idp.PartnerCertificateFile
})
Next
For Each sp As SSOServiceProviderModel In SPs
samlConfiguration.AddPartnerServiceProvider(New PartnerServiceProviderConfiguration With {
.Name = sp.Name,
.Description = sp.Description,
.AssertionConsumerServiceUrl = sp.AssertionConsumerServiceUrl,
.LocalCertificateFile = sp.LocalCertificateFile,
.LocalCertificatePassword = sp.LocalCertificatePassword
})
Next

SAMLController.Configuration = samlConfiguration

But when I call the Initiate SSO function it gives me an error.

As well as adding the partner identity providers you need to configure the local service provider.
For example:
samlConfiguration.LocalServiceProvider = New LocalServiceProvider With {
.Name = “xxx”
etc
}
You’ll see a complete example of this (in C# I’m afraid) in the ExampleServiceProvider’s Global.asax.cs.
The LoadSAMLConfigurationProgrammatically configures a local service provider and a partner identity provider.
This configuration can support multiple clients with a partner identity provider per client.
If you also need a separate service provider per client this is catered for by our multi-tenancy support.
The LoadMultiTenantedSAMLConfigurationProgrammatically method in Global.asax.cs demonstrates this.
Separate service providers per client or tenant is only required if the service provider name, assertion consumer service endpoint, or service provider certificate are different for each tenant.

[quote]
ComponentSpace - 9/28/2017
As well as adding the partner identity providers you need to configure the local service provider.
For example:
samlConfiguration.LocalServiceProvider = New LocalServiceProvider With {
.Name = “xxx”
etc
}
You’ll see a complete example of this (in C# I’m afraid) in the ExampleServiceProvider’s Global.asax.cs.
The LoadSAMLConfigurationProgrammatically configures a local service provider and a partner identity provider.
This configuration can support multiple clients with a partner identity provider per client.
If you also need a separate service provider per client this is catered for by our multi-tenancy support.
The LoadMultiTenantedSAMLConfigurationProgrammatically method in Global.asax.cs demonstrates this.
Separate service providers per client or tenant is only required if the service provider name, assertion consumer service endpoint, or service provider certificate are different for each tenant.
[/quote]

I'm loading these as described in the LoadMultiTenantedSAMLConfigurationProgrammatically method, and the trace file shows the multiple configurations loaded, but when ReceiveSSO is called, I receive a "Multiple SAML configurations exist but a configuration ID hasn't been specified." error. I'm using 2.8.6.0 of the DLLs. My tracefile looks like:

ComponentSpace.SAML2 Verbose: 0 : 21892/26: 12/19/2017 9:15:38 PM: Initiation of SSO to the partner identity provider 6b4f8b57dbe1722c4198449e79ec8c912769e73efcbc13dda026e96b1e1718ed has completed successfully.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: ComponentSpace.SAML2, Version=2.8.6.0, Culture=neutral, PublicKeyToken=7c51d97b3a0a8ff9, .NET v4.6 build (evaluation license).
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: CLR: 4.0.30319.42000, OS: Microsoft Windows NT 10.0.15063.0, Account: IIS APPPOOL\ProdSupport, Culture: English (United States)
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: The SAML configurations have been set.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: Initializing the SAML environment.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: The SAML configuration with ID Default has been loaded.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: The local service provider is VendorServiceProvider.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: The partner identity providers are:
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: TSA_HRIS_X509
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: 6b4f8b57dbe1722c4198449e79ec8c912769e73efcbc13dda026e96b1e1718ed
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: The SAML configuration with ID 6b4f8b57dbe1722c4198449e79ec8c912769e73efcbc13dda026e96b1e1718ee has been loaded.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: The local service provider is 6b4f8b57dbe1722c4198449e79ec8c912769e73efcbc13dda026e96b1e1718ee.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: The partner identity providers are:
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: AcmeSSP
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: The SAML configuration with ID i9aSAML20SP_UAT has been loaded.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: The local service provider is i9aSAML20SP_UAT.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: The partner identity providers are:
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: http://idp.ssocircle.com
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: The SAML environment has been successfuly initialized.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: Exception: ComponentSpace.SAML2.Exceptions.SAMLConfigurationException: Multiple SAML configurations exist but a configuration ID hasn't been specified.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:02 PM: at ComponentSpace.SAML2.Configuration.SAMLConfigurations.GetConfiguration(String configurationID) in C:\Sandboxes\ComponentSpace\SAMLv20\Library\Configuration\SAMLConfigurations.cs:line 174
at ComponentSpace.SAML2.Configuration.Resolver.SAMLConfigurationResolver.GetLocalServiceProviderConfiguration(String configurationID) in C:\Sandboxes\ComponentSpace\SAMLv20\Library\Configuration\Resolver\SAMLConfigurationResolver.cs:line 60
at ComponentSpace.SAML2.InternalSAMLServiceProvider..ctor() in C:\Sandboxes\ComponentSpace\SAMLv20\Library\InternalSAMLServiceProvider.cs:line 809
at ComponentSpace.SAML2.SAMLServiceProvider.ReceiveSSO(HttpRequest httpRequest, Boolean& isInResponseTo, String& partnerIdP, String& authnContext, String& userName, IDictionary& attributes, String& relayState) in C:\Sandboxes\ComponentSpace\SAMLv20\Library\SAMLServiceProvider.cs:line 453
at integration_SAML_AssertService.PageLoad(Object sender, EventArgs e) in D:\projects\i9AInternal\I9A\Prod-5.0.4.23\wwwroot\integration\SAML\AssertService.aspx.vb:line 57
at BasePage.Page_Load(Object sender, EventArgs e) in D:\projects\i9AInternal\I9A\Prod-5.0.4.23\wwwroot\App_Code\BasePage.vb:line 341
at System.Web.UI.Control.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.integration_saml_assertservice_aspx.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)

ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:10 PM: Exception: ComponentSpace.SAML2.Exceptions.SAMLConfigurationException: Multiple SAML configurations exist but a configuration ID hasn't been specified.
ComponentSpace.SAML2 Verbose: 0 : 4608/8: 12/19/2017 9:55:10 PM: at ComponentSpace.SAML2.Configuration.SAMLConfigurations.GetConfiguration(String configurationID) in C:\Sandboxes\ComponentSpace\SAMLv20\Library\Configuration\SAMLConfigurations.cs:line 174
at ComponentSpace.SAML2.Configuration.Resolver.SAMLConfigurationResolver.GetLocalServiceProviderConfiguration(String configurationID) in C:\Sandboxes\ComponentSpace\SAMLv20\Library\Configuration\Resolver\SAMLConfigurationResolver.cs:line 60
at ComponentSpace.SAML2.InternalSAMLServiceProvider..ctor() in C:\Sandboxes\ComponentSpace\SAMLv20\Library\InternalSAMLServiceProvider.cs:line 809
at ComponentSpace.SAML2.SAMLServiceProvider.ReceiveSSO(HttpRequest httpRequest, Boolean& isInResponseTo, String& partnerIdP, String& authnContext, String& userName, IDictionary& attributes, String& relayState) in C:\Sandboxes\ComponentSpace\SAMLv20\Library\SAMLServiceProvider.cs:line 453
at integration_SAML_AssertService.PageLoad(Object sender, EventArgs e) in D:\projects\i9AInternal\I9A\Prod-5.0.4.23\wwwroot\integration\SAML\AssertService.aspx.vb:line 57
at BasePage.Page_Load(Object sender, EventArgs e) in D:\projects\i9AInternal\I9A\Prod-5.0.4.23\wwwroot\App_Code\BasePage.vb:line 341
at System.Web.UI.Control.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
at System.Web.UI.Page.ProcessRequest()
at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context)
at System.Web.UI.Page.ProcessRequest(HttpContext context)
at ASP.integration_saml_assertservice_aspx.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)

My Code looks like the following:
Page_Load()
SAMLHelper.GetSAMLConfigurations(g_sEnvironment)


SAMLServiceProvider.ReceiveSSO(Request, isInResponseTo, partnerIdp, sAuthn, sUsername, attributes, Nothing)
If String.IsNullOrEmpty(targetUrl) Then
targetUrl = "~/"
End If

End PageLoad
Public Shared Sub GetSAMLConfigurations(ByVal gEnvironment As String)
Dim oAppKeyController As New AppKeyController
Dim oAppKeySAML As New i9Advantage.Domain.DataTypes.AppKeySAML
Dim oAppKeySAMLList As New i9Advantage.Domain.DataTypes.AppKeysSAMLList
Dim oSAMLConfigurations As New SAMLConfigurations

If SAMLController.Configurations.Configurations.Count <= 0 Then
oAppKeySAMLList = oAppKeyController.GetAllAppKeysSAMLList()
For Each oAppKeySAML In oAppKeySAMLList
AddSAMLConfiguration(oSAMLConfigurations, oAppKeySAML, gEnvironment)
Next
SAMLController.Configurations = oSAMLConfigurations
End If
End Sub

Private Shared Sub AddSAMLConfiguration(ByVal oSAMLConfigs As SAMLConfigurations, ByVal appKeySAML As i9Advantage.Domain.DataTypes.AppKeySAML, ByVal gEnvironment As String)
Dim serviceProviderConfig As LocalServiceProviderConfiguration = New LocalServiceProviderConfiguration()
Dim partnerIDPCOnfig As PartnerIdentityProviderConfiguration = New PartnerIdentityProviderConfiguration()
Dim entID As Integer = 0
Dim compID As Integer = 0
Dim oSamlConfiguration As SAMLConfiguration = New SAMLConfiguration()

If oSAMLConfigs.Configurations.Count <= 0 Then
oSamlConfiguration = New SAMLConfiguration()
oSamlConfiguration.ID = "Default"
Else
If appKeySAML.ServiceProviderIdp.Trim.Length <= 0 Then
oSamlConfiguration = oSAMLConfigs.GetConfiguration("Default")
Else
oSamlConfiguration = New SAMLConfiguration()
oSamlConfiguration.ID = appKeySAML.ServiceProviderIdp.Trim
End If
End If

If Not oSamlConfiguration Is Nothing Then
If oSamlConfiguration.ID <> "Default" Then
oSamlConfiguration.LocalServiceProviderConfiguration = SAMLHelper.GetServiceProviderFromAppKeySAML(appKeySAML)
Else
oSamlConfiguration.LocalServiceProviderConfiguration = SAMLHelper.GetDefaultServiceProvider()
End If
partnerIDPCOnfig.Name = appKeySAML.PartnerIdp
partnerIDPCOnfig.SignAuthnRequest = appKeySAML.SignAuthnRequest
partnerIDPCOnfig.WantSAMLResponseSigned = appKeySAML.WantSAMLResponseSigned
partnerIDPCOnfig.WantAssertionEncrypted = appKeySAML.WantAssertionEncrypted
partnerIDPCOnfig.WantAssertionSigned = appKeySAML.WantAssertionSigned

If appKeySAML.SingleSignOnServiceURL.ToLower.Contains(BINDING_POST) Then
Dim iIndex As Integer = appKeySAML.SingleSignOnServiceURL.ToLower.IndexOf(BINDING_POST)
partnerIDPCOnfig.SingleSignOnServiceUrl = appKeySAML.SingleSignOnServiceURL.ToLower.Substring(0, iIndex)
partnerIDPCOnfig.SingleSignOnServiceBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Else
partnerIDPCOnfig.SingleSignOnServiceUrl = appKeySAML.SingleSignOnServiceURL
End If

If appKeySAML.SingleLogOutServiceURL.ToLower.Contains(BINDING_POST) Then
Dim iIndex As Integer = appKeySAML.SingleLogOutServiceURL.ToLower.IndexOf(BINDING_POST)
partnerIDPCOnfig.SingleLogoutServiceUrl = appKeySAML.SingleSignOnServiceURL.ToLower.Substring(0, iIndex)
partnerIDPCOnfig.SingleLogoutServiceBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Else
partnerIDPCOnfig.SingleLogoutServiceUrl = appKeySAML.SingleSignOnServiceURL
End If

If appKeySAML.PartnerCertificateFile.Trim.Length > 0 Then
partnerIDPCOnfig.PartnerCertificateFile = appKeySAML.PartnerCertificateFile
End If
partnerIDPCOnfig.UseEmbeddedCertificate = appKeySAML.UseEmbeddedCertificate

If gEnvironment.ToUpper = "PRD" OrElse gEnvironment.ToUpper = "PROD" OrElse gEnvironment.ToUpper = "TRN" OrElse gEnvironment.ToUpper = "TRAIN" Then
partnerIDPCOnfig.DisableRecipientCheck = False
partnerIDPCOnfig.DisableTimePeriodCheck = False
Else
partnerIDPCOnfig.DisableRecipientCheck = True
partnerIDPCOnfig.DisableTimePeriodCheck = True
End If
oSamlConfiguration.AddPartnerIdentityProvider(partnerIDPCOnfig)

If oSAMLConfigs.Configurations.Count <= 0 Then
oSAMLConfigs.AddConfiguration(oSamlConfiguration)
Else
If oSamlConfiguration.ID <> "Default" Then
oSAMLConfigs.AddConfiguration(oSamlConfiguration)
End If
End If
End If
End Sub

Public Shared Function GetDefaultServiceProvider() As LocalServiceProviderConfiguration
Dim serviceProviderConfig As LocalServiceProviderConfiguration = New LocalServiceProviderConfiguration()
serviceProviderConfig.Name = "I9Advantage"
serviceProviderConfig.AssertionConsumerServiceUrl = "~/integration/SAML/AssertService.aspx"
serviceProviderConfig.LocalCertificateFile = ""
serviceProviderConfig.LocalCertificatePassword = ""
Return serviceProviderConfig
End Function

Private Shared Function GetServiceProviderFromAppKeySAML(ByVal appKeySAML As i9Advantage.Domain.DataTypes.AppKeySAML) As LocalServiceProviderConfiguration
Dim serviceProviderConfig As LocalServiceProviderConfiguration = New LocalServiceProviderConfiguration()
serviceProviderConfig.Name = appKeySAML.ServiceProviderIdp
serviceProviderConfig.AssertionConsumerServiceUrl = appKeySAML.AssertionConsumerServiceURL
serviceProviderConfig.LocalCertificateFile = appKeySAML.LocalCertificateFile
serviceProviderConfig.LocalCertificatePassword = appKeySAML.LocalCertificatePassword
Return serviceProviderConfig
End Function

As there are multiple SAML configurations, you need to specify which configuration to use prior to calling any of the SAML SSO/SLO APIs.
You do this by setting the SAMLController.ConfigurationID.
For example:

SAMLController.ConfigurationID = “tenant1”;
SAMLServiceProvider.ReceiveSSO(…);

The SAMLController.ConfigurationID must match the SAMLConfiguration.ID of the SAML configuration that should be used to process the SSO/SLO.
SAMLController.ConfigurationID is a static property but the ID is stored in the SAML SSO session state so there are no issues with processing multiple simultaneous SSO/SLO requests using different SAML configurations.

[quote]
ComponentSpace - 12/19/2017
As there are multiple SAML configurations, you need to specify which configuration to use prior to calling any of the SAML SSO/SLO APIs.
You do this by setting the SAMLController.ConfigurationID.
For example:

SAMLController.ConfigurationID = "tenant1";
SAMLServiceProvider.ReceiveSSO(...);

The SAMLController.ConfigurationID must match the SAMLConfiguration.ID of the SAML configuration that should be used to process the SSO/SLO.
SAMLController.ConfigurationID is a static property but the ID is stored in the SAML SSO session state so there are no issues with processing multiple simultaneous SSO/SLO requests using different SAML configurations.
[/quote]

Right before the 'SAMLServiceProvider.ReceiveSSO' i do not know anything about the user or the configuration related to that user. So how do we distinguish between the configurations?

One common strategy is to identify the tenant by the URL. For example, different tenants might have different sub-domain names or there might be a query string parameter identifying them.
You would use the tenant identification to determine the configuration ID.
Please note that this is required to identify different tenants within a multi-tenanted application.
It’s not related to specific users within a tenancy.

[quote]
ComponentSpace - 6/11/2018
One common strategy is to identify the tenant by the URL. For example, different tenants might have different sub-domain names or there might be a query string parameter identifying them.
You would use the tenant identification to determine the configuration ID.
Please note that this is required to identify different tenants within a multi-tenanted application.
It's not related to specific users within a tenancy.
[/quote]

Well, i do not have either of these (no sub-domain, no query etc. just). In that case, what'd you be recommend?

Just to confirm, is your application a multi-tenancy application?
Assuming so, how do you distinguish between different tenants elsewhere in your application?

[quote]
ComponentSpace - 6/11/2018
Just to confirm, is your application a multi-tenancy application?
Assuming so, how do you distinguish between different tenants elsewhere in your application?
[/quote]

Yes and i can distinguish between them with their top-level accounts. You can think as, phone1:extension1, phone1:extension2 etc.

So the user has to be authenticated before you know which tenant they belong to?

[quote]
ComponentSpace - 6/12/2018
So the user has to be authenticated before you know which tenant they belong to?
[/quote]

Yes, that's right. Any thoughts?

Do you definitely need multiple SAML configurations?
You can have multiple partner providers configured in a single SAML application.

[quote]
ComponentSpace - 6/12/2018
Do you definitely need multiple SAML configurations?
You can have multiple partner providers configured in a single SAML application.
[/quote]

Yes because accounts themselves will define configurations not me. And for each account i'll switch to its configuration.

I’m not sure if there is an easy solution to this.
You want to switch to the correct SAML configuration based off information about the authenticated user identified by information in the SAML assertion.
However, the user is authenticated by receiving and processing the SAML assertion which requires the correct SAML configuration to be used.
The simplest solution is to have each tenant use a slightly different URL (eg a query string parameter to identify the tenant).
Otherwise, the only thing I can think of is to peak at the SAML response and extract whatever you need to determine the SAML configuration to use.
For example:


// Peak at the SAML response.
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.PreserveWhitespace = true;
xmlDocument.LoadXml(Encoding.UTF8.GetString(Convert.FromBase64String(Request[“SAMLResponse”])));

SAMLResponse samlResponse = new SAMLResponse(xmlDocument.DocumentElement);

// Use information in the SAML response/assertion to determine the SAML configuration ID.
// Details not shown.
string configurationID = “todo”;

// Select the SAML configuration.
SAMLController.ConfigurationID = configurationID;

// Receive and process the SAML response.
SAMLServiceProvider.ReceiveSSO(Request, out isInResponseTo, out partnerIdP, out authnContext, out userName, out attributes, out targetUrl);


[quote]
ComponentSpace - 6/13/2018
I'm not sure if there is an easy solution to this.
You want to switch to the correct SAML configuration based off information about the authenticated user identified by information in the SAML assertion.
However, the user is authenticated by receiving and processing the SAML assertion which requires the correct SAML configuration to be used.
The simplest solution is to have each tenant use a slightly different URL (eg a query string parameter to identify the tenant).
Otherwise, the only thing I can think of is to peak at the SAML response and extract whatever you need to determine the SAML configuration to use.
For example:


// Peak at the SAML response.
XmlDocument xmlDocument = new XmlDocument();
xmldocument.PreserveWhitespace = true;
xmldocument.LoadXml(Encoding.UTF8.GetString(Convert.FromBase64String(Request["SAMLResponse"])));

SAMLResponse samlResponse = new SAMLResponse(xmldocument.DocumentElement);

// Use information in the SAML response/assertion to determine the SAML configuration ID.
// Details not shown.
string configurationID = "todo";

// Select the SAML configuration.
SAMLController.ConfigurationID = configurationID;

// Receive and process the SAML response.
SAMLServiceProvider.ReceiveSSO(Request, out isInResponseTo, out partnerIdP, out authnContext, out userName, out attributes, out targetUrl);


[/quote]

I think, this'll solve the issue. Thanks a lot.

You’re welcome.

I’ve tried to retrieve NameID as
ServiceProvider.ReceiveSAMLResponseByHTTPPost(Request, out var samlResponseXml, out _);
var samlResponse = new SAMLResponse(samlResponseXml);
var samlAssertion = (SAMLAssertion)samlResponse.Assertions[0];
var userName = samlAssertion.Subject.NameID.NameIdentifier;


but i’ve got following error
Unable to cast object of type ‘System.Xml.XmlElement’ to type ‘ComponentSpace.SAML2.Assertions.SAMLAssertion’.

am i missing something here?

P.S: i’ve followed example in LowLevelAPI > SP-Initiated > SAML2ServiceProvider > SAML > AssertionConsumerService.aspx.cs:100

The SAML assertion embedded in the SAML response may be plain or encrypted as well as being signed or unsigned.
For a signed unencrypted SAML assertion, samlResponse.Assertions[0] will return an XmlElement as this is required for signature verification.
I suggest calling SAMLResponse.GetUnsignedAssertion instead as this handles both unsigned and signed assertions.


var samlAssertion = samlResponse.GetUnsignedAssertion();


[quote]
ComponentSpace - 6/20/2018
The SAML assertion embedded in the SAML response may be plain or encrypted as well as being signed or unsigned.
For a signed unencrypted SAML assertion, samlResponse.Assertions[0] will return an XmlElement as this is required for signature verification.
I suggest calling SAMLResponse.GetUnsignedAssertion instead as this handles both unsigned and signed assertions.


var samlAssertion = samlResponse.GetUnsignedAssertion();


[/quote]

Thanks, it worked.

You’re welcome.