django-sso-oauth
Django OAuth authentication for the admin interface and the frontend.
Replaces the default Django admin login with an OAuth 2.0 / OpenID Connect flow, and provides the same flow for regular (non-staff) site users. After a successful OAuth exchange, the user's session is maintained by a lightweight middleware that maps the OAuth identity to a Django user.
Requirements
- Python >= 3.6
- Django >= 3.2
requestsPyJWT
Installation
pip install django-sso-oauth
Configuration
1. Environment variables
Set the following variables in your .env file or environment:
| Variable | Description |
|---|---|
DJANGO_SSO_OAUTH_BASE_URL |
Base URL of the OAuth provider (e.g. https://sso.example.com) |
DJANGO_SSO_OAUTH_CLIENT_ID |
OAuth client ID |
DJANGO_SSO_OAUTH_CLIENT_SECRET |
OAuth client secret |
DJANGO_SSO_OAUTH_REDIRECT_URL |
Redirect URI registered with the OAuth provider (e.g. https://yourapp.example.com/sso/callback/) |
DJANGO_SSO_OAUTH_AFTER_LOGIN_URL |
Where to land after an admin login (default: admin:index) |
DJANGO_SSO_OAUTH_USER_AFTER_LOGIN_URL |
Where to land after a frontend login (default: index) |
DJANGO_SSO_OAUTH_AFTER_LOGOUT_URL |
Where to land after logout (default: same as DJANGO_SSO_OAUTH_USER_AFTER_LOGIN_URL) |
The three URL variables accept either a URL name (admin:index, dashboard) or an absolute path
(/dashboard/). A single DJANGO_SSO_OAUTH_REDIRECT_URL is shared by both the admin and the
frontend flow.
2. Add to INSTALLED_APPS
INSTALLED_APPS = [
...
"django_sso_oauth",
]
3. Add middleware
Add OauthSessionMiddleware after AuthenticationMiddleware in your MIDDLEWARE setting:
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django_sso_oauth.middleware.OauthSessionMiddleware", # <-- add here
...
]
The middleware only sets request.user when an SSO session is present, so ordinary Django
authentication (e.g. a local superuser) keeps working alongside SSO.
4. Wire up URLs
In your project's urls.py, override the default admin login, add the frontend login/logout
routes, and add the shared OAuth callback:
from django.contrib import admin
from django.urls import path, include
from django_sso_oauth import views as sso_views
urlpatterns = [
path("admin/login/", sso_views.login_admin), # replaces default admin login
path("user/login/", sso_views.login_user, name="userlogin"),
path("user/logout/", sso_views.logout_user, name="userlogout"),
path("admin/", admin.site.urls),
path("sso/callback/", sso_views.oauth_redirect), # OAuth callback
...
]
Important:
admin/login/must be declared beforeadmin.site.urlsso it takes precedence. Thesso/callback/path must matchDJANGO_SSO_OAUTH_REDIRECT_URL.
5. Frontend usage
Point Django's LOGIN_URL at the frontend login view so @login_required sends users into the SSO
flow:
LOGIN_URL = "/user/login/"
@login_required appends ?next=<original path>, which is carried through the OAuth round trip and
honoured on the way back, so users land on the page they originally asked for.
How it works
- A user visiting
/admin/is redirected to/admin/login/; a user visiting a@login_requiredpage is redirected to/user/login/. - The login view redirects to the OAuth provider's authorization endpoint with a signed
stateparameter carrying the target (adminoruser) and thenextURL. - The provider redirects back to the callback with an authorization code and the
state. oauth_redirectverifies thestate(rejecting forged or expired ones), exchanges the code for an access token, decodes the JWT to extract the user's email (upnorunique_nameclaim), and looks up the corresponding Django user.- The user must exist and be active. For the
admintarget the user must also beis_staff; otherwise the request is rejected with 403 and no session is created. - The email is stored in the session;
OauthSessionMiddlewarerestores the user on every subsequent request. /user/logout/flushes the Django session. The provider's own session is left untouched, so a subsequent login is a silent SSO re-login.
The Django user must already exist in the database. User provisioning is not handled by this package.
Upgrading from 1.x
Version 2.0 is a breaking change:
| 1.x | 2.x |
|---|---|
views.login |
views.login_admin |
| — | views.login_user, views.logout_user (new) |
middleware.OauthAdminSessionMiddleware |
middleware.OauthSessionMiddleware |
middleware placed after SessionMiddleware |
must be placed after AuthenticationMiddleware |
Also note:
- The callback now requires a valid signed
stateparameter. Since the login views generate it, no configuration change is needed — but bookmarked or replayed callback URLs will now 400. - The middleware no longer forces
request.usertoAnonymousUserwhen there is no SSO session. - Error responses now return their intended status code (1.x returned
200for every error path).
Running the tests
python runtests.py
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_sso_oauth-2.0.0.tar.gz.
File metadata
- Download URL: django_sso_oauth-2.0.0.tar.gz
- Upload date:
- Size: 11.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.10.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
533ffd1a0f7140c7878ad7fcf7b57e7486fa91997cb822c922809656de798911
|
|
| MD5 |
93cafe4d24df6bc05ffc87219792fef4
|
|
| BLAKE2b-256 |
aaf3b96da78d2eba117a742ff4ad3a4e825c97dfb0b48f01b05b2dba69da1d43
|
File details
Details for the file django_sso_oauth-2.0.0-py3-none-any.whl.
File metadata
- Download URL: django_sso_oauth-2.0.0-py3-none-any.whl
- Upload date:
- Size: 10.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.10.17
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c381d4630353c78e5b3bf29c3eb53f844fed01e82d44505b77e790849ae01c29
|
|
| MD5 |
2cae37074048187491fde7aca58b2412
|
|
| BLAKE2b-256 |
65887b834f0c4733f849c001e233b78a09535b8a5676e403c671a3d787a84cf0
|