Skip to main content

A pluggable Django authentication system with JWT cookies, email verification, password reset, and TOTP-based 2FA with backup codes.

Project description

django-auth-system

A pluggable Django authentication system with JWT cookies, email verification, password reset, and TOTP-based 2FA with backup codes.

Built on Django REST Framework + SimpleJWT — designed for cookie-based SPA / mobile clients.


Features

  • Signup with email + password, auto-deactivate until email is verified
  • Email verification via token link
  • Login — returns JWT in HttpOnly cookies (or hands off to 2FA)
  • Logout — blacklists the refresh token, clears cookies
  • Token refresh — silent refresh via the refresh-token cookie
  • Password reset — request + confirm (token-based)
  • Change password — authenticated user changes own password
  • Change email — request + confirm (token-based)
  • TOTP 2FA — setup via QR code, enable/disable, backup codes
  • Backup codes — generate, list, consume, regenerate (10 codes by default)
  • Pending session — Redis-backed 2FA handoff (5-minute TTL)
  • Django admin integration — manage 2FA per user
  • OpenAPI schema — drf-spectacular extension for cookie-JWT auth
  • Email authentication backend — authenticate by email, not username
  • Enterprise Auth — support for ADFS (SAML/OIDC)
  • Social Auth — built-in API integration for python-social-auth (Google, Facebook, GitHub, etc.)
  • Rate limiting — login, signup, password-reset, and 2FA-verify throttles
  • Session invalidation — password/email change invalidates all existing JWT tokens
  • Secure email change — pending email stored in Redis, not in URL params
  • Configurable session hash — optional update_session_auth_hash() support

Requirements

Dependency Version
Python 3.10+
Django 4.2+
djangorestframework 3.14+
djangorestframework-simplejwt 5.3+
pyotp 2.8+
qrcode 7.4+
redis 5.0+
drf-spectacular 0.27+

Installation

pip install django-auth-system

Add to INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    "rest_framework",
    "rest_framework_simplejwt",
    "drf_spectacular",
    "social_django", # If using social/enterprise auth
    "auth_system",
    ...
]

Include the URLs:

# urls.py
urlpatterns = [
    path("api/auth/", include("auth_system.urls")),
]

Run migrations:

python manage.py migrate auth_system

Configuration

All settings live under the AUTH_SYSTEM dict in your settings.py:

AUTH_SYSTEM = {
    # JWT
    "JWT_ACCESS_TOKEN_LIFETIME": timedelta(minutes=15),
    "JWT_REFRESH_TOKEN_LIFETIME": timedelta(days=7),
    "JWT_ACCESS_COOKIE_NAME": "access_token",
    "JWT_REFRESH_COOKIE_NAME": "refresh_token",
    "JWT_COOKIE_SECURE": True,          # set False for local dev over HTTP
    "JWT_COOKIE_SAMESITE": "Lax",
    "JWT_COOKIE_HTTPONLY": True,
    # Redis
    "REDIS_URL": "redis://127.0.0.1:6379/0",
    "PENDING_SESSION_TTL": 300,          # seconds (2FA handoff window)
    "PENDING_SESSION_PREFIX": "auth:pending:",
    "PENDING_EMAIL_TTL": 3600,           # seconds (email change window)
    # 2FA
    "TOTP_ISSUER_NAME": "AuthSystem",
    "BACKUP_CODES_COUNT": 10,
    # Session
    "UPDATE_SESSION_AUTH_HASH": False,   # set True for session-based auth clients
    # Rate limiting — set None to disable
    "LOGIN_THROTTLE_RATES": {
        "login": "10/min",
        "signup": "5/min",
        "password_reset": "5/min",
        "verify_2fa": "10/min",
    },
    # Social Auth
    "SOCIAL_AUTH_SUCCESS_REDIRECT_URL": "/",
    "SOCIAL_AUTH_ERROR_REDIRECT_URL": "/login?error=true",
}

You also need standard Django settings:

AUTH_USER_MODEL = "your_app.User"   # or django's default
FRONTEND_URL = "https://your-frontend.com"
DEFAULT_FROM_EMAIL = "noreply@your-domain.com"
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"

Authentication backends

Add the custom email-based authentication backend (if your User model uses email as the unique identifier):

AUTHENTICATION_BACKENDS = [
    "social_core.backends.google.GoogleOAuth2",  # Example social auth
    "social_core.backends.saml.SAMLAuth",        # Example ADFS SAML
    "auth_system.authentication.EmailAuthBackend",
    "django.contrib.auth.backends.ModelBackend",
]

To install the enterprise and social extensions, use:

pip install django-auth-system[enterprise]

DRF settings

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "auth_system.authentication.CookieJWTAuthentication",
    ],
    "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
}

SimpleJWT (required for token blacklisting)

INSTALLED_APPS += ["rest_framework_simplejwt.token_blacklist"]

API Endpoints

Method Path Auth Description
POST /api/auth/signup/ public Create account
GET /api/auth/verify-account/?uid=&token= public Verify email
POST /api/auth/login/ public Login (password)
POST /api/auth/logout/ cookie JWT Logout, blacklist token
POST /api/auth/refresh/ refresh cookie Refresh access token
POST /api/auth/password-reset/ public Request password reset
POST /api/auth/password-reset-confirm/ public Confirm password reset
POST /api/auth/change-password/ cookie JWT Change password
POST /api/auth/change-email/ cookie JWT Request email change
GET /api/auth/change-email-confirm/ public Confirm email change
POST /api/auth/2fa/setup/ cookie JWT Generate TOTP secret + QR
POST /api/auth/2fa/enable/ cookie JWT Enable 2FA (verify TOTP)
POST /api/auth/2fa/disable/ cookie JWT Disable 2FA (password + TOTP)
POST /api/auth/2fa/verify-login/ public Complete 2FA login step
GET /api/auth/2fa/backup-codes/ cookie JWT List backup codes
POST /api/auth/2fa/backup-codes/ cookie JWT Regenerate backup codes
GET /api/auth/social/<provider>/login/ public Start Social/SAML/OIDC flow
GET/POST /api/auth/social/<provider>/complete/ public Complete Social Auth flow

Session Invalidation

Each user's TwoFactor record has a token_version field (default 0). Every JWT token embeds this version. When any of these events occur, the version is incremented and all existing JWT tokens become invalid:

  • Password changed (via change-password/ or password-reset-confirm/)
  • Email changed (via change-email-confirm/)

This protects against token replay after sensitive account changes.


2FA Login Flow

┌──────────┐    POST /login/         ┌──────────┐
│          │  ──────────────────────► │          │
│  Client  │    {email, password}     │  Server  │
│          │  ◄────────────────────── │          │
└──────────┘    {requires_2fa: true,  └──────────┘
                  session_token: uuid}

┌──────────┐    POST /2fa/verify-login/  ┌──────────┐
│          │  ──────────────────────────► │          │
│  Client  │    {session_token, code}     │  Server  │
│          │  ◄────────────────────────── │          │
└──────────┘    Set-Cookie: access_token  └──────────┘
                 Set-Cookie: refresh_token

Development

git clone https://github.com/your-username/django-auth-system
cd django-auth-system
python -m venv .venv && .venv\Scripts\activate
pip install -e ".[dev]"

Running tests

pytest tests/ -v

Requires a local Redis instance on 127.0.0.1:6379 or override REDIS_URL in tests/settings.py.


License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_auth_system-1.0.1.tar.gz (28.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_auth_system-1.0.1-py3-none-any.whl (35.4 kB view details)

Uploaded Python 3

File details

Details for the file django_auth_system-1.0.1.tar.gz.

File metadata

  • Download URL: django_auth_system-1.0.1.tar.gz
  • Upload date:
  • Size: 28.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for django_auth_system-1.0.1.tar.gz
Algorithm Hash digest
SHA256 044094b46d358fc48a8990a802eb0d0389f195fc194f9a36bd99090bcfd98194
MD5 44097900b3e2d421c3bcfcc61d5ff1b3
BLAKE2b-256 901ff491ddfa9cdb765b778349d57243376d457bf66a8c40976b30bc64e26545

See more details on using hashes here.

File details

Details for the file django_auth_system-1.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_auth_system-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 afd9ac27f3b5f1fe82f3a2cf94585d66a82b1e37ab2b51d54fcdb688d6ab5a90
MD5 944a7df721a3dcb70c9a5325139fa710
BLAKE2b-256 455d23f26b486c43b1e40d848579100f9405d19c0b59d24d3671e2704ac12a71

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page