Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
1 result

ssoauth

  • Clone with SSH
  • Clone with HTTPS
  • Art Lukyanchyk's avatar
    Art authored
    df063350
    History
    Name Last commit Last update
    ssoauth
    .gitignore
    AUTHORS
    LICENSE
    README.md
    setup.py

    Minimal Intro:

    • SSO: Single Sign On
    • SLO: Single Log Out
    • SP: Service Provider (your web app)
    • IdP: Identity Provider (server with some dreadful software like Shibboleth)
    • Metadata/Meta: an XML that describes SP or IdP (or some other entity)
    • SAML/SAML2: It's just another XML-based enterprise-grade standard that will make you cry blood and shit bricks

    Necessary Stuff

    • Binary dependencies: sudo apt install libxml2-dev libxslt1-dev xmlsec1 libxmlsec1-dev pkg-config
    • Python dependencies: see requirements.txt or setup.py
    • Add the app into INSTALLED_APPS
    • Include the ssoauth urls.py into the project urls.py urlpatterns:
      • Without a path/prefix: youre done.
      • With a path/prefix:
        • Reconsider it. It's highly recommended to include ssoauth without a prefix/path to avoid issues with apps like contrib.admin and wagtail that provide their own log in pages.
        • If you really need to use a path/prefix, make sure to set a setting LOGIN_URL = urls.reverse_lazy("sso-login")

    Development Setup

    • Should work with zero additional configuration.
    • You can use localhost:8000/dev/ (might change depending on your configuration) to access the dev view with all its helper features.

    Advanced development setup

    If you are not sure whether you need it: you don't need it. Use this only if you want an actual SSO with SAML2. For extra details see the default settings in ssoauth.app_settings.defaults. You might also need SSL, try using nginx for it.

    """ settings/dev.py """
    import os, socket
    from django import urls
    
    IDP_META_URL = "https://idp-test.it.hs-hannover.de/idp/shibboleth"
    IDP_LOGOUT_URL = "https://idp-test.it.hs-hannover.de/idp/profile/Logout"
    
    SP_KEY = "{project_settings}/cert/sp.key"
    SP_CERT = "{project_settings}/cert/sp.pem"
    
    SP_HOST = "localhost"
    SP_PORT = 8000
    SP_SSL = False
    
    SP_FORCE_ENTITY_ID = "dev-id-{0}-{1}".format(socket.gethostname(), os.path.dirname(os.path.dirname(__file__)))  # too many localhosts around

    Overriding Log In Pages of Other Apps

    There are some apps like django.contrib.admin or wagtail that will simply ignore LOGIN_URL and use their own log in page. If this behavior is undesirable and you would prefer using ssoauth instead, add the following into your urls.py (before including URLs of that other app):

    re_path(r"^(?:\w+/)?login/?$", ssoauth_views.LogInView.as_view(already_authenticated_403=True)),
    • Adjust the path if required
    • Optional argument already_authenticated_403=True is used to avoid redirect loops (e.g. caused by django.contrib.admin). You can also use already_authenticated_redirect="url-name".

    Regarding Logging Out

    After logging out locally, user will be redirected to one of the following (with this priority):

    • ?next= GET value (Note: instead of next use use django.contrib.auth.REDIRECT_FIELD_NAME)
    • LOGOUT_REDIRECT_URL (vanilla django setting), recommended values are:
      • LOGOUT_REDIRECT_URL = None for the default behavior
      • LOGOUT_REDIRECT_URL = urls.reverse_lazy("sso-logout-idp") if you want to instantly initiate IDP log out, possibly triggering SLO
      • LOGOUT_REDIRECT_URL = urls.reverse_lazy("sso-logged-out-locally")
    • Default: redirect to the view that asks users what to do next. Don't forget to override template ssoauth/logged_out_locally.html

    Advanced Logging Out and SLO

    If unsure, ignore this section.

    SLO: SLO/SLS is disabled by default. If you want to try your luck with SLO you should add to your project settings SP_SLS_ENABLED = True

    Currently only IdP-initiated SLO is supported by this app. The only supported binding type is HTTP-Redirect due to the limitations of the underlying library used.

    For SLO with HTTP-Redirect to work, the SLS page must be included as <iframe>. Your server and/or browser might restrict such behavior. Start with setting SP_SLS_X_FRAME_OPTIONS (check ssoauth.app_settings.defaults). If you have nginx serving pages to users, you might need to configure x-frame-options for the SLS view (Only the SLS view, nowhere else!). Additionally you might need to configure CSP on the web server on the IdP side. Anyways it will most likely be a lot of fun for you.

    Groups and Permissions

    Users receive groups using SSO. For this to work, you need:

    • some groups in your django project (see django.contrib.auth groups)
    • groups with exactly the same names provided by the IDP
      • create a group in the IDM
      • make sure IDM provides it to the IDP
      • make sure IDP provides it to your SP
    • you might want to predefine some groups in the project settings (see ssoauth default config for details)
      • these groups will be created automatically (when migrating) and will receive the specified permissions
      • e.g. you probably want a superuser group, see the example below
    PREDEFINED_GROUPS = {
        "my_project_superusers": [ssoauth.SUPERUSER_PERM_CODENAME],
    }

    Production Settings

    This example might be incomplete. See ssoauth.app_settings.defaults for additional info

    """ settings/prod.py """
    from django import urls
    
    SP_HOST = "foobar.it.hs-hannover.de"  # FQDN of your SP
    IDP_META_URL = "https://idp.hs-hannover.de/idp/shibboleth"  # production
    IDP_LOGOUT_URL = "https://idp.it.hs-hannover.de/idp/profile/Logout"  # web page for IdP logout (might initiate SLO)
    
    LOGIN_URL = urls.reverse_lazy("sso-login")  # django setting

    Certs

    • if you don't have a cert yet you can create one (and it doesn't need to be signed to use for SAML2 encryption):
    openssl req -newkey rsa:16384 -x509 -days 3650 -nodes -out sp.pem -keyout sp.key
    • create cert directory:
      • inside of project settings directory if it's a package
      • next to project settings.py file if it's a module
    • ./cert/sp.key put the private key here
    • ./cert/sp.pem put the certificate here, signing is optional
    • if you prefer your keys somewhere else, set SP_KEY and SP_CERT settings

    Add an SP to an IdP

    • Ask for assistance. Seriously.
    • Please try on the test IdP before you brick the production!
    • Grab your meta
      • Run your project.
      • Find meta of your SP (relative path /saml2/meta)
      • Use Ctrl+U ("view source") to get the actual XML, otherwise your browser could mess it up
    • IdP:
      • SSH to the IdP and locate the Shibboleth directory, most likely /opt/shibboleth-idp/
      • put your meta into a new file in ./metadata/ and give it a nice verbose name
      • edit ./conf/metadata-providers.xml
        • create a new <MetadataProvider .../> element, your best guess is to copy an existing line that belongs to some existing Django project
        • id should be unique
        • metadataFile should point on your new metadata
        • edit ./conf/attribute-filter.xml
      • systemctl restart tomcat8
      • make sure that IDP works
        • if IDP does not work, rollback your changes and restart the IDP again