Thoryn

Quickstarts · django

Django 5 — Hub login with `mozilla-django-oidc`

Wire OAuth2 / OIDC into a Django 5 app. Five steps, ~15 lines of settings.

Tested against:framework: Django 5.1oidcLib: mozilla-django-oidc@4.0

Django + Thoryn quickstart architecture — mozilla-django-oidc routes through Hub to your federation member; request.user becomes the OIDC-authenticated user

Prereqs

  • Python 3.12+
  • Django 5+
  • A Thoryn account

Step 1 — Register a confidential client

hub clients create \
  --name "My Django app" \
  --redirect-uri "http://localhost:8000/oidc/callback/" \
  --grant-types authorization_code,refresh_token \
  --scopes "openid email profile"

Step 2 — Install

pip install mozilla-django-oidc

Step 3 — Configure

settings.py:

INSTALLED_APPS = [
    # ... your apps ...
    "mozilla_django_oidc",
]
 
AUTHENTICATION_BACKENDS = [
    "mozilla_django_oidc.auth.OIDCAuthenticationBackend",
]
 
OIDC_RP_CLIENT_ID = os.environ["THORYN_CLIENT_ID"]
OIDC_RP_CLIENT_SECRET = os.environ["THORYN_CLIENT_SECRET"]
OIDC_OP_AUTHORIZATION_ENDPOINT = "https://hub.thoryn.org/oauth2/authorize"
OIDC_OP_TOKEN_ENDPOINT = "https://hub.thoryn.org/oauth2/token"
OIDC_OP_USER_ENDPOINT = "https://hub.thoryn.org/userinfo"
OIDC_OP_JWKS_ENDPOINT = "https://hub.thoryn.org/.well-known/jwks.json"
OIDC_RP_SIGN_ALGO = "RS256"
 
LOGIN_REDIRECT_URL = "/"
LOGOUT_REDIRECT_URL = "/"

urls.py:

urlpatterns = [
    # ... your routes ...
    path("oidc/", include("mozilla_django_oidc.urls")),
]

Step 4 — Use the user

from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
 
@login_required
def home(request):
    return JsonResponse({
        "name": request.user.get_full_name(),
        "email": request.user.email,
    })

Step 5 — Run it

THORYN_CLIENT_ID=... THORYN_CLIENT_SECRET=... python manage.py runserver

http://localhost:8000/oidc/authenticate/ redirects to Hub.

What's next

  • Hub — How it works
  • Override OIDCAuthenticationBackend.create_user to JIT-create User rows from claims

Troubleshooting

  • auth_request_params collision: if you customise OIDC params (state, nonce), make sure you're not also overriding mozilla-django-oidc's defaults.
  • Sessions cleared on every request: check SESSION_COOKIE_DOMAIN matches your origin.