Skip to content

Using Django Microsoft SSO outside Django Admin

Django Microsoft SSO aims for simplicity, that's why the primary focus is on the Admin login logic. But this package can be used outside Django Admin, in a custom login page. To do so, you can follow the steps below.

This is the Tip of the Iceberg

In real-life projects, user customer login involves more than just a login button. You need to implement many features like OTP, Captcha, "Recover Password", "Remember Me", "Login with Passkey" etc. This documentation shows a simple implementation to demonstrate how to use Django Microsoft SSO outside Django Admin, but for more complex UX requisites, please check full solutions like django-allauth, or incremental solutions like django-otp, django-recaptcha, django-passkeys, etc.

Add Django Microsoft SSO templates to your login page

Inside your login template, just add these two lines:

  • {% include 'microsoft_sso/login_sso.html' %} inside <body>
  • {% static 'django_microsoft_sso/microsoft_button.css' %} inside <head>

Login template example

{% load static %}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Page Login</title>
        <link rel="stylesheet" href="{% static 'django_google_sso/google_button.css' %}">
        <link rel="stylesheet" href="{% static 'django_microsoft_sso/microsoft_button.css' %}">
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/css/bootstrap.min.css" rel="stylesheet"
              integrity="sha384-SgOJa3DmI69IUzQ2PVdRZhwQ+dy64/BUtbMJw1MZ8t5HZApcHrRKUc4W0kG879m7" crossorigin="anonymous">
        <style>
            body {
                background-color: #f8f9fa;
            }
            .microsoft-login-btn, .google-login-btn, .github-login-btn {
                padding: 6px 4px;
                height: 36px;
            }
        </style>
    </head>
    <body class="container d-flex flex-column vh-100">
        <div class="d-flex flex-column w-100">
            {% if messages %}
                {% for message in messages %}
                    <div class="alert
                                {% if message.tags == 'error' %}alert-danger{% else %}alert-{{ message.tags }}{% endif %}" role="alert">
                        {{ message }}
                    </div>
                {% endfor %}
            {% endif %}
        </div>
        <div class="d-flex flex-column justify-content-center align-items-center flex-grow-1">
            <div class="card p-4 d-flex align-items-center" style="width: 22rem;">
                <div class="h4">Django Microsoft SSO</div>
                {% include 'google_sso/login_sso.html' %}
                <a href="{% url 'admin:index' %}" class="mt-2">Go to Admin</a>
            </div>
        </div>
    </body>
</html>

The include command will add the login button to your template for all django-sso installed in the project.

Define per-request parameters

In the case you need different behavior for the login to Admin and login to Django pages, you can define this using callables on the Django Microsoft SSO settings. For example:

Setting Login to Admin Login to Pages
MICROSOFT_SSO_ALLOWABLE_DOMAINS ["example.com"] ["*"]
MICROSOFT_SSO_LOGIN_FAILED_URL "admin:login" "index"
MICROSOFT_SSO_NEXT_URL "admin:index" "secret"
MICROSOFT_SSO_SESSION_COOKIE_AGE 3600 86400
MICROSOFT_SSO_STAFF_LIST [...] []
MICROSOFT_SSO_SUPERUSER_LIST [...] []

You can config almost all settings per request

You can config different Microsoft credentials, Scopes, Default Locale, etc. Please check the Settings and Sites docs for more details.

Settings logic example

# settings.py
from django_microsoft_sso.helpers import is_admin_path


def get_sso_config(request):
    config = {
        "admin": {
            "allowable_domains": env.get_or_default("MICROSOFT_SSO_ALLOWABLE_DOMAINS", []),
            "login_failed_url": "admin:login",
            "next_url": "admin:index",
            "session_cookie_age": 3600,  # 1 hour - default
            "staff_list": env.get_or_default("MICROSOFT_SSO_STAFF_LIST", []),
            "superuser_list": env.get_or_default("MICROSOFT_SSO_SUPERUSER_LIST", []),
            "auto_create_first_superuser": True,  # Create superuser on first eligible user login
        },
        "pages": {
            "allowable_domains": ["*"],  # Allow all domains
            "login_failed_url": "index",
            "next_url": "secret",
            "session_cookie_age": 86400,  # 24 hours
            "staff_list": [],
            "superuser_list": [],
            "auto_create_first_superuser": False,
        },
    }
    if is_admin_path(request):
        logger.debug("Returning Admin SSO configuration")
        return config["admin"]
    else:
        logger.debug("Returning Pages SSO configuration")
        return config["pages"]


# Configure settings as callables
MICROSOFT_SSO_ALLOWABLE_DOMAINS = lambda request: get_sso_config(request)[
    "allowable_domains"
]
MICROSOFT_SSO_AUTO_CREATE_FIRST_SUPERUSER = lambda request: get_sso_config(request)[
    "auto_create_first_superuser"
]
MICROSOFT_SSO_STAFF_LIST = lambda request: get_sso_config(request)["staff_list"]
MICROSOFT_SSO_SUPERUSER_LIST = lambda request: get_sso_config(request)["superuser_list"]
MICROSOFT_SSO_NEXT_URL = lambda request: get_sso_config(request)["next_url"]
MICROSOFT_SSO_SESSION_COOKIE_AGE = lambda request: get_sso_config(request)[
    "session_cookie_age"
]
MICROSOFT_SSO_LOGIN_FAILED_URL = lambda request: get_sso_config(request)["login_failed_url"]

Toggle Microsoft SSO between Admin and Page logins

Finally, if you want to toggle between Admin and Page login, you can enable/disable Microsoft SSO using the MICROSOFT_SSO_PAGES_ENABLED and MICROSOFT_SSO_ADMIN_ENABLED. For example, if you want to enable Microsoft SSO only for Page login:

# settings.py

# Enable or disable globally
MICROSOFT_SSO_ENABLED = True

# Enable or Disable per request
MICROSOFT_SSO_ADMIN_ENABLED = False
MICROSOFT_SSO_PAGES_ENABLED = True

How Package knows if the request is for Admin or Page login?

The package uses the is_admin_path and is_page_path helpers to check if the request.path starts with the admin path. To find the admin path, the package uses the SSO_ADMIN_ROUTE setting (default: admin:index).

# settings.py
from django_microsoft_sso.helpers import is_admin_path, is_page_path

SSO_ADMIN_ROUTE = "admin:index"  # Default admin route

MICROSOFT_SSO_ENABLED = True
MICROSOFT_SSO_ADMIN_ENABLED = is_admin_path  # Same as True
MICROSOFT_SSO_PAGES_ENABLED = is_page_path  # Same as True