Search code examples
itfoxtec-identity-saml2

Using multiple Id providers with ITfoxtec Identity SAML 2 library


I'm adding SSO support to a service, and I have the basic code working.

However, the service needs to support multiple customers, each with their own IdP, and I've hit a bit of a problem trying to work out how to do this.

Assuming I'm understanding it correctly the login flow goes something like this:

  • User hits the login button in our service
  • The service uses some information from the user to identify the customer/IdP and creates a suitable Saml2Configuration object with the appropriate URLs for that IdP
  • The service then sends an authentication request to the IdP
  • The IdP sends an authentication response to the service's assertion consumer service endpoint
  • The response is parsed and, assuming it's valid, the user is authenticated with the service appropriately

However, the sticking point is in the assertion consumer endpoint; in order for the response to be parsed, we need a Saml2AuthnResponse object. To create one of those, we need a Saml2Configuration object, which includes information such as the SAML signing cert, so the response can be validated.

But, in order to create the correct Saml2Configuration object we need to know which IdP it's come from. That information is included in the SAML response (e.g. as the Issuer field), but we can't read that info without a config object, and we can't create one of those without knowing which IdP the response is coming from...

At first I thought we could just pass the customer ID via the RelayState parameter, but I can't get the RelayState from the authentication response until I create the Sam2PostBinding and read the response, which I can't do until I've got a Saml2Configuration object. Same issue.

How do I resolve this catch-22 situation?


Solution

  • You can provide a AssertionConsumerService (acs) endpoint that includes a URL GET parameter with the customer ID ../mysite/acs?customerid=xxx and then pars the customerid parameter into the method:

    public async Task<IActionResult> AssertionConsumerService([FromQuery] string customerId)
    

    An alternative and cleaner solution is to add FoxIDs in between the IdPs and your application. Then FoxIDs handle the trust to multiple SAML 2.0 IdPs and the IdP-dependent validations. Then you application only need to trust one IdP, which would be a SAML 2.0 (or OpenID Connect) down-party configured in FoxIDs.

    You can configure the SAML 2.0 bridge (SAML to SAML or SAML to OIDC) in a free FoxIDs tenant.