Django guide¶
These instructions use the CDH Federated Auth django app (FA-app), part of the Django Shared Core (DSC) project.
This app simplifies setting up SAML in Django, and uses DjangoSaml2 and PySAML2 libraries under the hood.
Library Setup¶
Dependencies¶
Depending on which configuration you use, any of these Linux packages may be required:
libxml2
libxml2-dev
libxlst1-dev
python-dev
pkg-config
xmlsec1
For the python side, you only need to include the DSC library to your dependency list:
cdh-django-core[federated-auth] @ git+https://github.com/DH-IT-Portal-Development/django-shared-core.git@<version>
This will pull in all required dependencies. Substitute
<version>
with the latest release tag.Note
If you use other apps of the DSC project, you should add
federated-auth
to the existing list of optional dependencies.
Django configuration¶
For this guide, we will be adding SAML support in such a way that it can either run without or with SAML (as default). However, we will also provide some notes on how to add SAML support as an additional authentication backend.
Create a new file
saml_settings.py
next to the project’ssettings.py
, and add the following code:from django.urls import reverse_lazy from os import path from cdh.federated_auth.saml.settings import * _BASE_DIR = path.dirname(os.path.dirname(__file__)) SAML_CONFIG = create_saml_config( base_url='<app_hostname>', name='<app_name>', key_file=path.join(_BASE_DIR, 'certs/private.key'), cert_file=path.join(_BASE_DIR, 'certs/public.cert'), idp_metadata='https://login.uu.nl/nidp/saml2/metadata', contact_given_name='<contact_name>', contact_email='<contact_email>', ) AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', 'djangosaml2.backends.Saml2Backend', ) LOGIN_URL = reverse_lazy('saml2_login')
Change the following values:
<app_hostname>
: the hostname of the app, includinghttps://
<app_name>
: the name of your application<contact_name>
: the name of the team managing this application<contact_email>
: the email address of the team managing this application. ITS will use this email address as a contact when they make changes to the IdP that requires changes on the SP as well.AUTHENTICATION_BACKENDS
: if you want to keep using other authentication backends, you’ll need to add those here as well.LOGIN_URL
: This will make SAML the default page when Django redirects the user trying to access a login-required page. If you want to use multiple login backends, you should omit this setting and provide a link to this view on your regular login page instead.
These settings are for the production IdP. To use the acceptation IdP, change
login.uu.nl
tologin.acc.uu.nl
(inidp_metadata
). You can also use the URL of the Development IdP here, if you are using that.(Optional) These settings assume you use the default Django user model and corresponding SAML user attributes. If you use a different user model/more attributes, you need to add a custom attribute mapping. To do this, add the following to
saml_settings.py
:SAML_ATTRIBUTE_MAPPING = { 'uuShortID': ('username',), 'mail': ('email',), 'givenName': ('first_name',), 'uuPrefixedSn': ('last_name',), }
Add/change the attributes you use here. The key of this dict represents the name of the SAML attribute (the name you get in the response from the IdP), the value represents the name of the attribute in the Django user model.
Note
SurfConext uses different attribute names, which can be found on their wiki.
The following is an attribute map for the default Django user model, using SurfConext attribute names:
SAML_ATTRIBUTE_MAPPING = { 'uid': ('username',), 'mail': ('email',), 'givenName': ('first_name',), 'sn': ('last_name',), }
In your project’s root urlconf, add the following:
from django.conf import settings # [..] (your urlpatterns, etc) if hasattr(settings, 'SAML_CONFIG'): urlpatterns.append( path('saml/', include('djangosaml2.urls')), )
(Optional) If your app is going to use more than one authentication backend, you might have to use a different logout view. The default SAML logout view can only handle users logged in through SAML.
You can use the default Django logout view alongside the SAML version, which has the drawback that you will have to manually route your users to the correct one.
The FA-app provides a custom logout view that combines the default Django logout view with the SAML version. To use it, simply include the
cdh.federated_auth.saml.views.LogoutInitView
in your urlconf and direct your users to that view to log out.In your project’s
settings.py
, add the following to the bottom of the file:try: from .saml_settings import * # Only add the required apps/middleware if we could load the SAML config INSTALLED_APPS += SAML_APPS MIDDLEWARE += SAML_MIDDLEWARE except ImportError: print('Proceeding without SAML')
This requires that
INSTALLED_APPS
andMIDDLEWARE
as lists, not tuples.Create a folder called
certs
in the project root. This directory will contain your app’s signing certificate. Please follow the certificates guide to generate those. Make sure they the private key and certificate are calledprivate.key
andpublic.cert
respectively. (Or update the filenames insaml_settings.py
to the correct names).Warning
It is generally a very bad idea to store the certificates you use on deployed systems in git. However, you can store ‘development-only’ certs, and replace them manually during deployment on the server.
Double check that you are using the correct login/logout views everywhere in your app.
(Optional, but recommended). Test your configuration using the Development IdP
Contact ITS¶
You should now contact ITS and ask them to add your Service Provider to their
Identity Provider. Save the metadata (<app_hostname>/saml/metadata/
) as an
XML file and send this file to ITS, along with the message that you want to
register your application with their Identity Provider. Give the base URL of your
application and say if you want to make use of their acceptation or production
Identity Provider (depending on what URL you entered in the saml_settings.py
file).
Also indicate which fields you want the Identity Provider to pass back with a successful authentication redirect (such as solis-ID, full name, e-mail address, etc).
Once they have added you, you should be able to use SAML for authenticating your users.
Note
ITS requires SAML trace of a successful login/logout on the acceptation environment before they allow a production SP to be added to the IdP. Please see the SAML trace page for more info.
Tips¶
Example config file¶
In the guide we created a saml_settings.py
to store all the required SAML
configuration. As these settings vary between deployments (production,
acceptation, (local) development), it is a good idea to put this file in
your gitignore, and provide an ‘example file’ in your git repo instead.
(saml_settings.example.py
for example).
As we configured Django to only add all the SAML related urls etc if the
saml_settings.py
file is present, this will also enable local development
using the default authentication backend only.
Multiple IdP’s¶
The FA-app is meant to be used with one IdP only. However, if you have multiple
IdP which use the same config, you can use them simultaneously by adding the
following config override to create_saml_config
:
config_overrides={
'metadata': {
'remote': [
{'url': '<idp1_metadata_url>',},
{'url': '<idp2_metadata_url>',},
]
}
}
This can be used to in non-production environments to add both the ITS acceptation IdP and the Development IdP as a fallback option. (Useful if you want to be able to properly test SAML in the acceptation but also want to use custom test users).
When logging in, you will be prompted for which IdP you want to use.
If you want to use multiple IdP’s that use different configurations, please open an issue in the DSC repository.
Advanced options¶
This guide is meant to easily setup SAML for 90% of the use-cases, for developers unfamiliar with SAML. Thus, it does not fully explain all available (configuration) options.
If you have a special edge case or other requirements that require special
configuration, it is recommended you consult the
cdh.federated_auth.saml.settings
file for more in-depth documentation.