Skip to main content

Entra ID Authentication for Django

Attribution: This project is a fork of django-auth-adfs created by Joris Beckers and maintained by Snok.

docs PyPI version Python versions Django versions License Tests

A Django authentication backend for Microsoft Entra ID (formerly Azure AD). This project extends the foundation established by django-auth-adfs with specialized focus on Entra ID and Graph API integration.

Features

  • Integrates Django with Microsoft Entra ID (formerly Azure AD)
  • Provides seamless single sign on (SSO) for your Django project
  • Auto creates users and adds them to Django groups based on info received from Entra ID
  • Token Lifecycle Management (new): Automatically handles storing, refreshing, and encrypting access/refresh tokens
  • On-Behalf-Of Token Support (new): Simplifies access to Microsoft Graph API and other delegated access scenarios
  • Django Rest Framework (DRF) integration: Authenticate against your API with an Entra ID access token

While building on the original django-auth-adfs, we've focused specifically on the Entra ID authentication scenario with enhancements for token management, storing them so that your application can securely and seamlessly delegate access to Graph API on behalf of your users.

Installation

Python package:

pip install django-entra-auth

In your project's settings.py add these settings.

AUTHENTICATION_BACKENDS = (
    ...
    'django_entra_auth.backend.AdfsAuthCodeBackend',
    ...
)

INSTALLED_APPS = (
    ...
    # Needed for the auth redirect URI and static files to function
    'django_entra_auth',
    ...
)

# Basic configuration for Entra ID
# checkout the documentation for more settings
ENTRA_AUTH = {
    # Optional. Defaults to "login.microsoftonline.com".
    # Override for national clouds or compatible Entra ID hosts.
    "SERVER": "login.microsoftonline.com",
    "TENANT_ID": "your-tenant-id",
    "CLIENT_ID": "your-application-client-id",
    "RELYING_PARTY_ID": "your-application-client-id", # Often same as CLIENT_ID for Entra ID
    # OIDC Audience ("aud" claim). For Entra ID, CLIENT_ID
    "AUDIENCE": "your-application-client-id",
    # Set to False for Entra ID. Provide path for ADFS.
    "CA_BUNDLE": False,
    "CLAIM_MAPPING": {"first_name": "given_name",
                      "last_name": "family_name",
                      "email": "email"}, # Adjust based on claims from your provider
    # See documentation for TokenLifecycleMiddleware settings like:
    # "TOKEN_REFRESH_THRESHOLD", "STORE_OBO_TOKEN", "TOKEN_ENCRYPTION_SALT",
    # "LOGOUT_ON_TOKEN_REFRESH_FAILURE"
}

# Configure django to redirect users to the right URL for login
LOGIN_URL = "django_entra_auth:login"
LOGIN_REDIRECT_URL = "/" # Or wherever users should land after login

########################
# OPTIONAL SETTINGS
########################

MIDDLEWARE = (
    ...
    # Optional: Automatically manage access/refresh/OBO tokens in the session
    # Must be AFTER SessionMiddleware and AuthenticationMiddleware
    'django_entra_auth.middleware.TokenLifecycleMiddleware',
    # With this you can force a user to login without using
    # the LoginRequiredMixin on every view class
    #
    # You can specify URLs for which login is not enforced by
    # specifying them in the LOGIN_EXEMPT_URLS setting.
    'django_entra_auth.middleware.LoginRequiredMiddleware',
)

# Specify URLs exempt from LoginRequiredMiddleware (if used)
# LOGIN_EXEMPT_URLS = (
#     r'^/about/.*$',
#     r'^/legal/.*$',
# )

In your project's urls.py add these paths:

from django.urls import path, include

urlpatterns = [
    ...
    path('oauth2/', include('django_entra_auth.urls')),
]

This will add these paths to Django:

  • /oauth2/login where users are redirected to, to initiate the login with the identity provider.
  • /oauth2/login_no_sso where users are redirected to, but forcing a login screen.
  • /oauth2/callback where the identity provider redirects back to after login. Ensure your redirect URI in Entra ID/ADFS is set to this.
  • /oauth2/logout which logs out the user from both Django and the identity provider (if supported by provider).

Below is sample Django template code to use these paths depending if you'd like to use GET or POST requests. Logging out via GET was deprecated in Django 4.1.

  • Using GET requests (Login only):

    {# Logout requires POST #}
    <a href="{% url 'django_entra_auth:login' %}">Login</a>
    <a href="{% url 'django_entra_auth:login-no-sso' %}">Login (no SSO)</a>
    
  • Using POST requests:

    <form method="post" action="{% url 'django_entra_auth:logout' %}">
        {% csrf_token %}
        <button type="submit">Logout</button>
    </form>
    <form method="post" action="{% url 'django_entra_auth:login' %}">
        {% csrf_token %}
        <input type="hidden" name="next" value="{{ next }}">
        <button type="submit">Login</button>
    </form>
    <form method="post" action="{% url 'django_entra_auth:login-no-sso' %}">
        {% csrf_token %}
        <input type="hidden" name="next" value="{{ next }}">
        <button type="submit">Login (no SSO)</button>
    </form>
    

Contributing

Contributions to the code are more then welcome. For more details have a look at the CONTRIBUTING.rst file.

Metadata

Release files for django-entra-auth 1.16.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-entra-auth 1.16.1
File Size Uploaded Provenance
django_entra_auth-1.16.1.tar.gz 4.1 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-entra-auth 1.16.1
File Interpreter ABI Platform
django_entra_auth-1.16.1-py3-none-any.whl Python 3 none any Details

Total release size: 4.1 MB

Release files / django_entra_auth-1.16.1.tar.gz

Download URL django_entra_auth-1.16.1.tar.gz
Size 4.1 MB
Tags Source
SHA-256 checksum
How to use checksums
4286e103153560044077eaf1329669bc2156835dc9338383a98f14e284dc523e
BLAKE2b-256 checksum
How to use checksums
8e5e49ec6c72a8895e0e85e6c580c5b7f6485d2ae4ba85df6d8c8eacb3acf549
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / django_entra_auth-1.16.1-py3-none-any.whl

Download URL django_entra_auth-1.16.1-py3-none-any.whl
Size 22.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
11df2aac34b2423edd1f9c358cc1e9e8926805ff49712eb9e221cd232270f100
BLAKE2b-256 checksum
How to use checksums
10c788face54a46e6e9f6a554fb06083092436ed02fd0729c45dd030183e7d3f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Security for django-entra-auth 1.16.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.16.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page