Search code examples
securitysingle-sign-onsamlsaml-2.0idp

How to setup a single SAML app for all the tenants of multi-tenant app(having different domain urls)?


App Architecture:

  • We have a multi-tenant setup where every tenant has its own URL.
  • Every tenant has its own schema and configurations.

Problem:

We need a single SAML app that could be integrated with all the tenants.

Example tenant URLs: tenant1.myapp.com, tenant2.myapp.com, tenant3.myapp.com, etc.

We want all our tenants to be integrated with a single SAML app to authenticate users present in any of these tenants.

             |---------------- SAML App -----------------|
             |                     |                     |
             |                     |                     |
             |                     |                     |
          Tenant 1              Tenant 2              Tenant 3
     (tenant1.myapp.com)   (tenant2.myapp.com)   (tenant3.myapp.com)

Normally, we can have different SAML apps for different tenants, but it is leading us to maintain a lot of SAML apps, which we want to avoid.

We are attempting some solutions. We will update the answer here if any solution works. In the meantime, if anyone has any suggestions, please help.


Solution

  • We have found a solution to this problem. During redirection to the IdP login page, we send the tenant URL as the RelayState parameter in the request, which is returned to us in the SAML Assertion request body from IdP to our SP.

    • We wrote an AWS Lambda(along with API Gateway) to re-route the SAML Assertion request to the required tenant.
    • We used this RelayState parameter to know from which tenant this request originated.
    • We configured the API Gateway URL pointing to our lambda(SSO Router) as the ACS URL in our SAML App.

    The functioning of the Lambda: It picks the RelayState parameter from the SAML Assertion request body and redirects the request to the required tenant URL(present in the RelayState).

    Login to the App(any Tenant) ==> Redirection to Login Page ==> (On successful login) Redirected to Lambda(SSO Router) ==> Redirected to the tenant URL(present in the RelayState)

    We have written our Lambda in Python. Here is the Sample code:

        def lambda_handler(event, context):
            body = event.get('body')
            redirect_host = body.split('RelayState=https%3A%2F%2F')[1].split('%2')[0]
            # Here the request body is urlencoded and the URL will be of the form https://tenant1.myapp.com/ - we are only picking tenant1.myapp.com from the RelayState
            redirect_url = 'https://' + redirect_host + '/saml/?acs'
            # Our SAML redirection URL is of the form https://tenant1.myapp.com/saml/?acs
            logger.info(f"Redirecting To: {redirect_url}")
            return {
                'statusCode': 307, # Status code 307 is to preserve the method by which this URL was called. Using 302 changes the method to GET whereas the SAML request comes as a POST
                'headers': {
                    'Location': redirect_url,
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Access-Control-Allow-Origin': '*',
                },
                'body': body,
            }