imsweb / django-saml-sp

A Django application for running one or more SAML service providers (SP)
BSD 3-Clause "New" or "Revised" License
15 stars 10 forks source link

Possible to modify SAML settings? #11

Closed thefedoration closed 2 years ago

thefedoration commented 2 years ago

Is it possible to modify the settings that python3-saml will use? Specifically, I am looking to modify the requestedAuthnContext setting to false, in order to not pass the following in the authentication request:

<samlp:RequestedAuthnContext Comparison="exact">
     <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
    </samlp:RequestedAuthnContext>

I'm integrating with ADFS and it doesn't appear that the IdP for this version of ADFS can handle that kind of authentication mechanism.

Please let me know if I'm missing another setting that could modify the AuthnContext that is sent in the request.

thefedoration commented 2 years ago

Okay after doing some digging I see the settings used is determined by this property:

@property
def settings(self):
        settings_dict = json.loads(self.saml_settings)
        settings_dict.update(self.sp_settings)
        return settings_dict

It looks like IdP.saml_settings is a json field, but not accessible in the django admin. It also gets overwritten with each import of the XML file, so modifying settings there would not be a good idea. IdP.sp_settings has some defaults, but that is not configurable by people who use this package.

I'd like to recommend that we update this package to include another json field, which allows the users of this package to configure settings from the django admin on a per-IdP level. This would be useful to do things like require nameid in a particular format (unlike right now it's always unspecified)

What do you think?

thefedoration commented 2 years ago

In order to achieve what I currently need (disable requestedAuthnContext default setting), I monkeypatched the settings property using the SP_IDP_LOADER setting provided by this package.

This isn't the best long-term solution, ideally I would be able to have configurable settings per-IdP and be able to set those settings in the django admin. However, I think the right solution here would be to add a new JSONfield to the model in this package. Knowing that this might become available in a future release, I'm hesitant to introduce this database field into my own codebase right now, so here's how I'm doing it.

# in settings.py
SP_IDP_LOADER = "sso.utils.get_saml_idp"

# in sso.utils.py
def get_saml_idp(request, slug):
    """
    Custom loader for SAML IdP where we fetch by slug (default behavior)
    then monkeypatch the settings to override some defaults
    """
    import json
    from sp.models import IdP
    from django.shortcuts import get_object_or_404

    # override for ALL IdPs
    DEFAULT_SETTINGS_OVERRIDES = {'security': {'requestedAuthnContext': False}}

    # define the new settings property method
    def new_settings_property(self):
        settings_dict = json.loads(self.saml_settings)
        settings_dict.update(self.sp_settings)
        settings_dict.update(DEFAULT_SETTINGS_OVERRIDES)  # here's our override
        return settings_dict

    # monkeypatch the settings property for the IdP model
    IdP.settings = property(new_settings_property)

    # the standard method for fetching the IdP
    idp = get_object_or_404(IdP, slug=slug, is_active=True)
    return idp
dcwatson commented 2 years ago

Let me know if this does the trick for you. I'm going to push a new release in the next few weeks. At some point it might be worth adding a hook to customize all the python3-saml dict options, but for now I've just been adding specific fields.