Implement SAML Single Sign-On in your Django project quickly and easily.
Project description
Django SAML Toolkit
Quickly and easily add SAML Single Sign-On to your Django projects. This package is designed to be very simple for initial setup while also being easily customizable to meet all of your needs.
Installation
Dependencies (Linux)
The package xmlsec1 is required for this to work. On debian you can install it with the following:
sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl
Dependencies (Windows)
The python-xmlsec package on Windows is having some issues with hosting, so you can install it manually here:
pip install https://github.com/mehcode/python-xmlsec/releases/download/1.3.5/xmlsec-1.3.52.dev0-cp36-cp36m-win_amd64.whl
For more information here is the related issue.
Pip
pip install python3-saml-django
Django
settings.py
INSTALLED_APPS = [
...,
'django_saml'
]
AUTHENTICATION_BACKENDS = [
'django_saml.backends.SamlUserBackend',
...
]
urls.py
Django >= 2.0
urlpatterns = [
path('saml/', include('django_saml.urls')),
...
]
Django <= 1.11
urlpatterns = [
url(r'^saml/', include('django_saml.urls')),
...
]
Configuration
Required Settings
SP Information
You must provide information about your site to be published as metadata.
SAML_SP = {
"entityId": "https://<your_site>/saml/metadata/",
"assertionConsumerService": {
"url": "https://<your_site>/saml/acs/",
# DO NOT CHANGE THIS
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
},
"singleLogoutService": {
"url": "https://<your_site>/saml/sls/",
# DO NOT CHANGE THIS
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"NameIDFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified",
"x509cert": "<can also be loaded by file, see SAML_BASE_DIRECTORY>",
"privateKey": "<can also be loaded by file, see SAML_BASE_DIRECTORY>"
}
IdP Information
You must provide information about the IdP you will be using through one of the following means:
SAML_IDP = {
"entityId": "https://example.com/saml/metadata/",
"singleSignOnService": {
"url": "https://example.com/trust/saml2/http-post/sso/",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"singleLogoutService": {
"url": "https://example.com/trust/saml2/http-redirect/slo/",
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
},
"x509cert": "<cert here>"
}
SAML_IDP_FILE = os.path.join(BASE_DIR, 'idp_meta.xml')
SAML_IDP_URL = 'https://example.com/saml/metadata/'
Optional Settings
Setting | Description | Default | Example |
---|---|---|---|
SAML_STRICT | Incorrect SAML responses should be rejected. Should be True in production. | True | |
SAML_DEBUG | SAML warnings are displayed | False | |
SAML_CREATE_USER | New users are created on login if they don't exist | True | |
SAML_UPDATE_USER | Existing users are updated with information from SAML on login | False | |
SAML_IDP_METADATA_TIMEOUT | If using SAML_IDP_URL, the result will be cached for this many seconds before checking again. | 3600 | |
SAML_SECURITY | Advanced security settings | See below | See below |
SAML_CONTACT | Contact information for site maintainers | None | See below |
SAML_ORGANIZATION | Organization information | None | See below |
SAML_LOGIN_REDIRECT | URL to redirect users after a successful login | '/' | |
SAML_LOGOUT_REDIRECT | URL to redirect users after a successful logout | '/logged-out' | |
SAML_NO_USER_REDIRECT | URL to redirect users if SAML_CREATE_USER = False and the user doesn't exist | None (Raises PermissionDenied) | '/permission-error' |
SAML_USERNAME_ATTR | SAML attribute to use to look up users | 'uid' | 'email' |
SAML_ATTR_MAP | List of 2-tuples to map SAML attributes to Django user attributes | [] | [('givenName', 'first_name')] |
SAML_BASE_DIRECTORY | File path to load SP certificates. Must contain a 'certs' folder with 'sp.key' and 'sp.crt' inside. | None | os.path.join(BASE_DIR, 'saml') |
SAML_SECURITY Default and Example
SAML_SECURITY = {
"nameIdEncrypted": False,
"authnRequestsSigned": False,
"logoutRequestSigned": False,
"logoutResponseSigned": False,
"signMetadata": False,
"wantMessagesSigned": False,
"wantAssertionsSigned": False,
"wantNameId": True,
"wantNameIdEncrypted": False,
"wantAssertionsEncrypted": False,
"signatureAlgorithm": "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
"digestAlgorithm": "http://www.w3.org/2000/09/xmldsig#sha1"
}
SAML_CONTACT Example
SAML_CONTACT = {
"technical": {
"givenName": "Technology Director",
"emailAddress": "technology@thon.org"
},
"support": {
"givenName": "Lead Systems Admin",
"emailAddress": "systems@thon.org"
}
}
SAML_ORGANIZATION Example
SAML_ORGANIZATION = {
'en-US': {
'name': 'thon',
'displayname': 'THON',
'url': 'thon.org'
}
}
Advanced Configuration (Custom Backend)
For situations like advanced attribute mapping with groups, transforming SAML attributes, etc, you can create custom backends to use instead of the default.
Example:
from django_saml.backends import SamlUserBackend
class CustomSamlBackend(SamlUserBackend):
def clean_username(self, username):
"""Return the first part of the email address.
Example: test@example.com -> test.
"""
return username.split('@')[0]
def configure_user(self, session_data, user):
"""Custom attribute mapping with groups.
NOTE: ALL SAML attributes in session_data are arrays, even if there is only one element.
"""
# Call super() to take care of the simple attribute mapping in SAML_ATTR_MAP
user = super(CustomSamlBackend, self).configure_user(session_data, user)
for group_name in session_data['psMemberOf']:
group_name = group_name[5:]
g = Group.objects.get(name=group_name)
g.members.add(user)
return user
Credit
This project is a wrapper around OneLogin's python3-saml library.
Support
If you would like to support the development of this package, please consider donating to THON and supporting our mission.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for python3-saml-django-1.0.2.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 99e8773847920c68b349b5aaa6518125d926fd83a060ab081cf29399ea5e98e7 |
|
MD5 | 42518c5b2f7d177d2755f34c89bf4965 |
|
BLAKE2b-256 | 9142eb27fce56954de35a366c0654259d0d39e15ab56cb782003ff73b5792101 |
Hashes for python3_saml_django-1.0.2-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | eb508058dfe9b08a9622a11098f58c1452e4a843f506d56c25e138dcf9ea238c |
|
MD5 | 4555192ce2d37404300bb4f9dd879028 |
|
BLAKE2b-256 | 25f7a96211fcc5d6c1c1c7cf64f6e11f671fdab9880a0c790012af4b2e94f331 |