Metadata-Version: 2.1
Name: python3-saml-django
Version: 1.1.3
Summary: Implement SAML Single Sign-On in your Django project quickly and easily.
Home-page: https://github.com/penn-state-dance-marathon/python3-saml-django
Author: THON Technology
Author-email: technology@thon.org
License: UNKNOWN
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.
        
        #### Debian / Ubuntu:
        
        `sudo apt-get install libxml2-dev libxmlsec1-dev libxmlsec1-openssl`
        
        #### Red Hat / CentOs:
        
        `sudo yum install libxml2-devel xmlsec1-devel xmlsec1-openssl-devel libtool-ltdl-devel`
        
        ### 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](https://github.com/onelogin/python3-saml/issues/110). 
        
        ### Pip
        
        `pip install python3-saml-django`
        
        
        ### Django
        
        **settings.py**
        
        ```python
        INSTALLED_APPS = [
            ...,
            'django_saml'
        ]
        
        AUTHENTICATION_BACKENDS = [
            'django_saml.backends.SamlUserBackend',
            ...
        ]
        ```
        
        **urls.py**
        
        Django >= 2.0
        ```python
        urlpatterns = [
            path('saml/', include('django_saml.urls')),
            ...
        ]
        ```
        
        Django <= 1.11
        ```python
        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.
        ```python
        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:
        ```python
        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 | Path to redirect users after a successful login | '/' | 
        | SAML_LOGOUT_REDIRECT | Path to redirect users after a successful logout | '/logged-out' |
        | SAML_NO_USER_REDIRECT | Path 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_DESTINATION_HOST | Static value to compare with the SAML Destination attribute instead of reading from the request.  Useful for load balancers. | None | 'example.com'
        | SAML_DESTINATION_HTTPS | Companion for SAML_DESTINATION_HOST. Set to True if the destination will be over HTTPS but the final request will not be. | None | True
        | SAML_DESTINATION_PORT | Companion for SAML_DESTINATION_HOST. Set to a STRING of a number if you use a non-standard port that does not match SAML_DESTINATION_HTTPS. | None | '8080'
        
        **SAML_SECURITY** Default and Example
        ```python
        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
        ```python
        SAML_CONTACT = {
            "technical": {
                "givenName": "Technology Director",
                "emailAddress": "technology@thon.org"
            },
            "support": {
                "givenName": "Lead Systems Admin",
                "emailAddress": "systems@thon.org"
            }
        }
        ```
        
        **SAML_ORGANIZATION** Example
        ```python
        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:
        ```python
        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](https://github.com/onelogin/python3-saml/).
        
        ## Support
        
        If you would like to support the development of this package, please consider [donating to THON](https://donate.thon.org/index.cfm?fuseaction=donorDrive.event&eventID=1868) and supporting our mission.
        
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 1.11
Classifier: Framework :: Django :: 2.0
Classifier: Framework :: Django :: 2.1
Classifier: Framework :: Django :: 2.2
Classifier: Framework :: Django :: 3.0
Classifier: Framework :: Django :: 3.1
Classifier: Framework :: Django :: 3.2
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3
Description-Content-Type: text/markdown
Provides-Extra: test
