如何为多租户应用程序(具有不同域 URL)的所有租户设置单个 SAML 应用程序?
How to setup a single SAML app for all the tenants of multi-tenant app(having different domain urls)?
应用架构:
- 我们有一个多租户设置,每个租户都有自己的 URL。
- 每个租户都有自己的架构和配置。
问题:
我们需要一个可以与所有租户集成的单一 SAML 应用程序。
示例租户 URLs:tenant1.myapp.com、tenant2.myapp.com、tenant3.myapp.com 等
我们希望所有租户都与单个 SAML 应用程序集成,以对任何这些租户中存在的用户进行身份验证。
|---------------- SAML App -----------------|
| | |
| | |
| | |
Tenant 1 Tenant 2 Tenant 3
(tenant1.myapp.com) (tenant2.myapp.com) (tenant3.myapp.com)
通常情况下,我们可以为不同的租户使用不同的 SAML 应用程序,但这导致我们维护大量 SAML 应用程序,这是我们想要避免的。
我们正在尝试一些解决方案。如果任何解决方案有效,我们将在此处更新答案。同时,如果有人有什么建议,请帮忙。
我们已经找到解决这个问题的方法。
在重定向到 IdP 登录页面期间,我们将租户 URL 作为请求中的 RelayState
参数发送,该参数在从 IdP 到我们的 SP 的 SAML 断言请求正文中返回给我们。
- 我们编写了一个 AWS Lambda(以及 API 网关)来将 SAML 断言请求重新路由到所需的租户。
- 我们使用这个
RelayState
参数来了解这个请求来自哪个租户。
- 我们在 SAML 应用程序中将指向我们的 lambda(SSO 路由器)的 API 网关 URL 配置为 ACS URL。
Lambda 的功能:
它从 SAML 断言请求正文中选择 RelayState
参数并将请求重定向到所需的租户 URL(存在于 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)
我们已经在 Python 中编写了 Lambda。这是示例代码:
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,
}
应用架构:
- 我们有一个多租户设置,每个租户都有自己的 URL。
- 每个租户都有自己的架构和配置。
问题:
我们需要一个可以与所有租户集成的单一 SAML 应用程序。
示例租户 URLs:tenant1.myapp.com、tenant2.myapp.com、tenant3.myapp.com 等
我们希望所有租户都与单个 SAML 应用程序集成,以对任何这些租户中存在的用户进行身份验证。
|---------------- SAML App -----------------|
| | |
| | |
| | |
Tenant 1 Tenant 2 Tenant 3
(tenant1.myapp.com) (tenant2.myapp.com) (tenant3.myapp.com)
通常情况下,我们可以为不同的租户使用不同的 SAML 应用程序,但这导致我们维护大量 SAML 应用程序,这是我们想要避免的。
我们正在尝试一些解决方案。如果任何解决方案有效,我们将在此处更新答案。同时,如果有人有什么建议,请帮忙。
我们已经找到解决这个问题的方法。
在重定向到 IdP 登录页面期间,我们将租户 URL 作为请求中的 RelayState
参数发送,该参数在从 IdP 到我们的 SP 的 SAML 断言请求正文中返回给我们。
- 我们编写了一个 AWS Lambda(以及 API 网关)来将 SAML 断言请求重新路由到所需的租户。
- 我们使用这个
RelayState
参数来了解这个请求来自哪个租户。 - 我们在 SAML 应用程序中将指向我们的 lambda(SSO 路由器)的 API 网关 URL 配置为 ACS URL。
Lambda 的功能:
它从 SAML 断言请求正文中选择 RelayState
参数并将请求重定向到所需的租户 URL(存在于 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)
我们已经在 Python 中编写了 Lambda。这是示例代码:
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,
}