Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-tenant - tenant configured IDP parameters #357

Open
LiteWait opened this issue Nov 15, 2022 · 6 comments
Open

Multi-tenant - tenant configured IDP parameters #357

LiteWait opened this issue Nov 15, 2022 · 6 comments
Labels
Documentation Issues that document features and specific configuration/use cases

Comments

@LiteWait
Copy link

Our mutli-tenant single page application can have 1000's of tenants. We can not know which of these tenants want to use SAML 2 for authentication, nor can we know what their SAML2 IDP setup is.

I assume there is no support for gathering the IDP/SAML2 parameters dynamically (e.g. setup is stored in the DB by tenant) BUT it appears it wouldn't be that difficult to implement.

Am I correct?

@peppelinux
Copy link
Member

you can customize your login page and passing your custom parameters to your auth backend, this latter would select the saml2 authz or any other

feel free to share your thoughs here, probably I've miss something

@peppelinux peppelinux added the Documentation Issues that document features and specific configuration/use cases label Nov 15, 2022
@LiteWait
Copy link
Author

LiteWait commented Nov 15, 2022 via email

@peppelinux
Copy link
Member

@LiteWait
Copy link
Author

LiteWait commented Nov 15, 2022 via email

@peppelinux
Copy link
Member

well, you're asking for a way to get the IDP configuration from the DB instead that from settings

we can have this, would you like to push a PR to start the implementation of this feature?
that would be for a major release

@eshaan7
Copy link

eshaan7 commented Apr 12, 2023

Here's a rough spec of how I implemented multi-tenancy with djangosaml2.

In my implementation, I have an IdentityProvider model that stores the xml_metadata_url against a tenant.

from copy import deepcopy
from urllib.parse import unquote

from django.conf import settings
from django.core.exceptions import ValidationError
from saml2.config import SPConfig
from saml2.mdstore import SourceNotFound

def saml_config_loader(request):
    config = deepcopy(settings.SAML_CONFIG)

    # in case of login, we need to let user select the IdP.
    if request.resolver_match.url_name == "saml2_login":
        requested_idp_url_encoded = request.GET.get("idp")
        if not requested_idp_url_encoded:
            raise SourceNotFound
        requested_idp_url = unquote(requested_idp_url_encoded)
        try:
            validate_url(requested_idp_url)
        except ValidationError:
            raise SourceNotFound
        if not IdentityProvider.objects.filter(
            xml_metadata_url=requested_idp_url
        ).exists():
            raise SourceNotFound

        config["metadata"]["remote"] = [{"url": requested_idp_url}]

    # in case of ACS, we need to have all available IdPs in the metadata
    # so the correct one can be chosen by djangosaml2.
    elif request.resolver_match.url_name == "saml2_acs":
        config["metadata"]["remote"] = [
            {"url": url}
            for url in IdentityProvider.objects.values_list(
                "xml_metadata_url", flat=True
            )
        ]

    # delete `idp`, `scoping` and `idphint` or any other query param
    # to prevent djangosaml2 from processing it
    request.GET = {}

    return SPConfig().load(config)

In Django settings.py,

SAML_CONFIG_LOADER = "contrib.saml2.config.saml_config_loader"

SAML_CONFIG["metadata"] = {} # empty because dynamically loaded using saml_config_loader

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation Issues that document features and specific configuration/use cases
Projects
None yet
Development

No branches or pull requests

3 participants