Complete Django authentication package — JWT, RBAC, 2FA (TOTP), Magic Links, Passkeys (WebAuthn), Social Login, Breach Check, Organizations B2B, and multi-application support
Project description
Tenxyte Auth
Production-ready Django authentication in minutes — JWT, RBAC, 2FA, Magic Links, Passkeys, Social Login, Breach Check, Organizations (B2B), multi-application support.
Table of Contents
- Key Features
- Prerequisites
- Installation
- Quickstart (Dev vs Prod)
- Request & Response Examples
- Endpoints & Documentation
- Supported Databases
- Periodic Maintenance
- Customization & Extension
- Development & Testing
- Troubleshooting
- Contributing
- License & Support
Key Features
✨ Core Authentication
- JWT with access + refresh tokens, rotation, blacklisting
- Login via email / phone, Magic Links (passwordless), Passkeys (WebAuthn/FIDO2)
- Social Login — Google, GitHub, Microsoft, Facebook
- Multi-application support (
X-Access-Key/X-Access-Secret)
🔐 Security
- 2FA (TOTP) — Google Authenticator, Authy
- OTP via email and SMS, password breach check (HaveIBeenPwned, k-anonymity)
- Account lockout, session & device limits, rate limiting, CORS, security headers
- Audit logging
👥 RBAC
- Hierarchical roles, direct permissions (per-user and per-role)
- 8 decorators + DRF permission classes
🏢 Organizations (B2B)
- Multi-tenant with hierarchical tree, per-org roles & memberships
📱 Communication
- SMS: Twilio, NGH Corp, Console
- Email: Django (recommended), SendGrid, Console
⚙️ Shortcut Secure Mode
- One-line security preset:
TENXYTE_SHORTCUT_SECURE_MODE = 'medium' - Modes:
development/medium/robust— all individually overridable
Prerequisites
- Python 3.11+ (recommended)
pipand a virtual environment- Django 5.0+
- Database (PostgreSQL recommended for production)
Installation
pip install tenxyte
# Optional Extras
pip install tenxyte[twilio] # SMS via Twilio
pip install tenxyte[sendgrid] # Email via SendGrid
pip install tenxyte[mongodb] # MongoDB support
pip install tenxyte[postgres] # PostgreSQL
pip install tenxyte[mysql] # MySQL/MariaDB
pip install tenxyte[all] # Everything included
Quickstart — Development
1. Install
pip install tenxyte
2. Configure (settings.py + urls.py)
# settings.py — Add this at the END of the file (after INSTALLED_APPS, MIDDLEWARE, etc.)
import tenxyte
tenxyte.setup(globals())
# `tenxyte.setup(globals())` automatically injects the minimal required configuration:
# - Sets AUTH_USER_MODEL = 'tenxyte.User'
# - Adds 'rest_framework' and 'tenxyte' to INSTALLED_APPS
# - Configures DEFAULT_AUTHENTICATION_CLASSES and DEFAULT_SCHEMA_CLASS for REST_FRAMEWORK
# - Adds 'tenxyte.middleware.ApplicationAuthMiddleware' to MIDDLEWARE
# Note: It will NEVER overwrite settings you have already explicitly defined.
Understanding tenxyte.setup() VS tenxyte.setup(globals())
Passing globals() tells Tenxyte to directly modify the local dictionary of variables in your settings.py. This is the recommended and safest approach, as it strictly ensures that your INSTALLED_APPS, MIDDLEWARE, and REST_FRAMEWORK dictionaries are cleanly appended to without risking module resolution issues. Always place it at the very bottom of your settings.py.
# urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('api/auth/', include('tenxyte.urls')),
]
3. Bootstrap
python manage.py tenxyte_quickstart
# → makemigrations + migrate + seed roles/permissions + create Application
python manage.py runserver
⚠️ In
DEBUG=True, Tenxyte activates a "zero-configuration" behavior: ephemeral JWT,X-Access-Keydisabled, relaxed limits.
# First request — no special headers needed in dev!
curl -X POST http://localhost:8000/api/v1/auth/register/ \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "SecureP@ss1!", "first_name": "John", "last_name": "Doe"}'
Quickstart — Production
# settings.py
TENXYTE_JWT_SECRET_KEY = 'your-dedicated-long-random-secret' # REQUIRED
TENXYTE_SHORTCUT_SECURE_MODE = 'medium' # 'medium' | 'robust'
TENXYTE_APPLICATION_AUTH_ENABLED = True
- Configure a resilient DB backend (PostgreSQL recommended)
- Configure an email provider (e.g., SendGrid)
- Enable TLS/HTTPS in front
Request & Response Examples
In production, routes require
X-Access-KeyandX-Access-Secretheaders. InDEBUG=True(dev mode), they are not required.
Register
Request:
POST /api/v1/auth/register/
Content-Type: application/json
X-Access-Key: <app_key>
X-Access-Secret: <app_secret>
{
"email": "user@example.com",
"password": "SecureP@ss1!",
"first_name": "John",
"last_name": "Doe"
}
Response (201 Created):
{
"message": "Registration successful",
"user": {
"id": "1",
"email": "user@example.com",
"phone_country_code": null,
"phone_number": null,
"first_name": "John",
"last_name": "Doe",
"is_email_verified": false,
"is_phone_verified": false,
"is_2fa_enabled": false,
"roles": [],
"permissions": [],
"created_at": "2026-03-03T22:00:00Z",
"last_login": null
},
"verification_required": {
"email": true,
"phone": false
}
}
💡 To log the user in immediately after registration, include
"login": truein the request — JWT tokens will then be included in the response (access_token,refresh_token,token_type,expires_in).
Login (email)
Request:
POST /api/v1/auth/login/email/
Content-Type: application/json
X-Access-Key: <app_key>
X-Access-Secret: <app_secret>
{
"email": "user@example.com",
"password": "SecureP@ss1!"
}
Response (200 OK):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"device_summary": "desktop/windows",
"user": {
"id": "1",
"email": "user@example.com",
"phone": "",
"first_name": "John",
"last_name": "Doe",
"is_email_verified": false,
"is_phone_verified": false,
"is_2fa_enabled": false
}
}
If 2FA is enabled on the account, add
"totp_code": "123456"to the request.
curl — Quick Summary
# Register
curl -X POST http://localhost:8000/api/v1/auth/register/ \
-H "X-Access-Key: key" -H "X-Access-Secret: secret" \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "SecureP@ss1!", "first_name": "John", "last_name": "Doe"}'
# Login
curl -X POST http://localhost:8000/api/v1/auth/login/email/ \
-H "X-Access-Key: key" -H "X-Access-Secret: secret" \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "SecureP@ss1!"}'
# Authenticated request
curl http://localhost:8000/api/v1/auth/me/ \
-H "X-Access-Key: key" -H "X-Access-Secret: secret" \
-H "Authorization: Bearer <access_token>"
For more complete examples with responses, see: docs/endpoints.md
Endpoints & Documentation
Interactive Documentation
To enable the interactive documentation endpoints (Swagger UI, ReDoc, and OpenAPI Schema), make sure they are included in your routing, normally done in your main urls.py:
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView, SpectacularRedocView
from tenxyte.conf import auth_settings
api_prefix = auth_settings.API_PREFIX.strip('/')
urlpatterns = [
# ... your other urls
path(f'{api_prefix}/docs/schema/', SpectacularAPIView.as_view(), name='schema'),
path(f'{api_prefix}/docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
path(f'{api_prefix}/docs/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
]
Once configured, start your server:
python manage.py runserver
# Swagger UI: http://localhost:8000/api/v1/docs/
# ReDoc: http://localhost:8000/api/v1/docs/redoc/
# Schema: http://localhost:8000/api/v1/docs/schema/
- Static Site — Full documentation
- Postman Collection — Ready-to-use collection
- Endpoint Reference — All endpoints with curl examples
Endpoint Overview
| Category | Key Endpoints |
|---|---|
| Auth | register, login/email, login/phone, refresh, logout, logout/all |
| Social | social/google, social/github, social/microsoft, social/facebook |
| Magic Link | magic-link/request, magic-link/verify |
| Passkeys | webauthn/register/begin+complete, webauthn/authenticate/begin+complete |
| OTP | otp/request, otp/verify/email, otp/verify/phone |
| Password | password/reset/request, password/reset/confirm, password/change |
| 2FA | 2fa/setup, 2fa/confirm, 2fa/disable, 2fa/backup-codes |
| Profile | me/, me/roles/ |
| RBAC | roles/, permissions/, users/{id}/roles/, users/{id}/permissions/ |
| Applications | applications/ (CRUD + regenerate) |
Supported Databases
- ✅ SQLite — development
- ✅ PostgreSQL — recommended for production
- ✅ MySQL/MariaDB
- ✅ MongoDB — via
django-mongodb-backend
See DATABASE_SETUP.md for full per-database configuration.
MongoDB — Required Configuration
pip install tenxyte[mongodb]
# settings.py
AUTH_USER_MODEL = 'tenxyte.User'
DEFAULT_AUTO_FIELD = 'django_mongodb_backend.fields.ObjectIdAutoField'
DATABASES = {
'default': {
'ENGINE': 'django_mongodb_backend',
'NAME': 'tenxyte_db',
'HOST': 'localhost',
'PORT': 27017,
}
}
# Disable native migrations (integer PKs incompatible with ObjectId)
MIGRATION_MODULES = {
'contenttypes': None,
'auth': None,
}
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'tenxyte.middleware.CORSMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
# ❌ Remove: 'django.contrib.auth.middleware.AuthenticationMiddleware'
'django.contrib.messages.middleware.MessageMiddleware',
'tenxyte.middleware.ApplicationAuthMiddleware',
]
MongoDB — Django Admin Support
To use Django Admin with MongoDB, replace default admin/auth/contenttypes entries with custom configs that set ObjectIdAutoField.
Step 1 — apps.py of your main app:
from django.contrib.admin.apps import AdminConfig
from django.contrib.auth.apps import AuthConfig
from django.contrib.contenttypes.apps import ContentTypesConfig
class MongoAdminConfig(AdminConfig):
default_auto_field = "django_mongodb_backend.fields.ObjectIdAutoField"
class MongoAuthConfig(AuthConfig):
default_auto_field = "django_mongodb_backend.fields.ObjectIdAutoField"
class MongoContentTypesConfig(ContentTypesConfig):
default_auto_field = "django_mongodb_backend.fields.ObjectIdAutoField"
Step 2 — INSTALLED_APPS:
INSTALLED_APPS = [
# Replace the three Django defaults with your MongoDB versions:
'config.apps.MongoAdminConfig', # replaces 'django.contrib.admin'
'config.apps.MongoAuthConfig', # replaces 'django.contrib.auth'
'config.apps.MongoContentTypesConfig', # replaces 'django.contrib.contenttypes'
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'tenxyte',
]
Replace
configwith the name of your main Django app. Then, runpython manage.py makemigrations && python manage.py migrate— Django Admin will work correctly with MongoDB.
Periodic Maintenance
Tenxyte requires a few periodic tasks to maintain performance and security. Configure Celery Beat or a standard cron job:
-
Token Cleanup (Daily at 3 AM) Remove blacklisted JWT tokens and expired refresh/agent tokens:
from tenxyte.models import BlacklistedToken, RefreshToken, AgentToken BlacklistedToken.cleanup_expired() # Add similar logic for Refresh/Agent tokens based on expires_at
-
OTP & WebAuthn Purge (Every 15 minutes) Clear expired OTP codes and unused WebAuthn challenges:
from tenxyte.models import OTPCode, WebAuthnChallenge OTPCode.cleanup_expired() WebAuthnChallenge.cleanup_expired()
-
Audit Log Rotation (Monthly) To comply with GDPR, archive or delete old logs:
from django.utils import timezone from datetime import timedelta from tenxyte.models import AuditLog cutoff = timezone.now() - timedelta(days=90) AuditLog.objects.filter(timestamp__lt=cutoff).delete()
Customization & Extension
Tenxyte exposes abstract base classes: AbstractUser, AbstractRole, AbstractPermission, AbstractApplication.
# myapp/models.py
from tenxyte.models import AbstractUser
class CustomUser(AbstractUser):
company = models.CharField(max_length=100, blank=True)
class Meta(AbstractUser.Meta):
db_table = 'custom_users'
# settings.py
TENXYTE_USER_MODEL = 'myapp.CustomUser'
AUTH_USER_MODEL = 'myapp.CustomUser'
Same pattern for TENXYTE_ROLE_MODEL, TENXYTE_PERMISSION_MODEL, TENXYTE_APPLICATION_MODEL. Always inherit the parent Meta and set a custom db_table.
Configuration Reference
All 115+ settings documented in docs/settings.md.
Useful toggles for development:
TENXYTE_APPLICATION_AUTH_ENABLED = False # disables X-Access-Key check
TENXYTE_RATE_LIMITING_ENABLED = False
TENXYTE_ACCOUNT_LOCKOUT_ENABLED = False
TENXYTE_JWT_AUTH_ENABLED = False # testing only
Development & Testing
git clone https://github.com/tenxyte/tenxyte.git
pip install -e ".[dev]"
pytest # 1553 tests, 100% pass rate
pytest --cov=tenxyte --cov-report=html
Multi-DB Tests (requires a running server per backend):
pytest tests/multidb/ -o "DJANGO_SETTINGS_MODULE=tests.multidb.settings_sqlite"
pytest tests/multidb/ -o "DJANGO_SETTINGS_MODULE=tests.multidb.settings_pgsql"
pytest tests/multidb/ -o "DJANGO_SETTINGS_MODULE=tests.multidb.settings_mysql"
pytest tests/multidb/ -o "DJANGO_SETTINGS_MODULE=tests.multidb.settings_mongodb"
Frequently Asked Questions & Troubleshooting
MongoDB does not support AutoField/BigAutoField
→ Configure DEFAULT_AUTO_FIELD = 'django_mongodb_backend.fields.ObjectIdAutoField' and add MIGRATION_MODULES = {'contenttypes': None, 'auth': None}. For Django Admin, use the custom app configs described in the MongoDB Admin section.
Model instances without primary key value are unhashable
→ Same fix (MIGRATION_MODULES). If it persists, disconnect post_migrate signals for create_permissions and create_contenttypes.
ModuleNotFoundError: No module named 'rest_framework'
→ pip install djangorestframework
401 Unauthorized / JWT not working
→ Ensure all three headers are present: X-Access-Key, X-Access-Secret, Authorization: Bearer <token>.
No module named 'corsheaders'
→ Tenxyte includes built-in CORS middleware (tenxyte.middleware.CORSMiddleware). Remove corsheaders from your config.
Contributing
Contributions are welcome! A few simple rules:
- Open an issue before a major feature request.
- Fork → branch
feature/xxx→ PR with tests and changelog. - Respect commit conventions and add unit tests.
See CONTRIBUTING.md for more details.
License
MIT — see LICENSE.
Support
Changelog
See CHANGELOG.md for release history.
Project details
Release history Release notifications | RSS feed
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 tenxyte-0.9.2.5.tar.gz.
File metadata
- Download URL: tenxyte-0.9.2.5.tar.gz
- Upload date:
- Size: 568.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03295f8ff83667bd57fa7b1a5b8578b0fd1cd9000b6469ff5189b663c2e39f9e
|
|
| MD5 |
e337b28bdf5b69b284568c065f4ffc05
|
|
| BLAKE2b-256 |
98ac4cbbbcc8a23bbb8fcdbee0cb688b414b09d222822d786f2ee2d28fbe433d
|
Provenance
The following attestation bundles were made for tenxyte-0.9.2.5.tar.gz:
Publisher:
publish.yml on tenxyte/tenxyte
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tenxyte-0.9.2.5.tar.gz -
Subject digest:
03295f8ff83667bd57fa7b1a5b8578b0fd1cd9000b6469ff5189b663c2e39f9e - Sigstore transparency entry: 1068200466
- Sigstore integration time:
-
Permalink:
tenxyte/tenxyte@e869a2d4bd523cd0944f99d5b4c04b83ceeb48d6 -
Branch / Tag:
refs/tags/v0.9.1-core - Owner: https://github.com/tenxyte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e869a2d4bd523cd0944f99d5b4c04b83ceeb48d6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tenxyte-0.9.2.5-py3-none-any.whl.
File metadata
- Download URL: tenxyte-0.9.2.5-py3-none-any.whl
- Upload date:
- Size: 253.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
670d2d189aaec9c714c6e6b7838705328b9e65499a16cfbd246840a2e6565c99
|
|
| MD5 |
7fd8b8aa10ccf4f3fdf9fe6e6104654f
|
|
| BLAKE2b-256 |
6ec8c5ce554b77357adc3af6ea2fd0eb534d4a98fa57e947d01eb1bf46106e5a
|
Provenance
The following attestation bundles were made for tenxyte-0.9.2.5-py3-none-any.whl:
Publisher:
publish.yml on tenxyte/tenxyte
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tenxyte-0.9.2.5-py3-none-any.whl -
Subject digest:
670d2d189aaec9c714c6e6b7838705328b9e65499a16cfbd246840a2e6565c99 - Sigstore transparency entry: 1068200598
- Sigstore integration time:
-
Permalink:
tenxyte/tenxyte@e869a2d4bd523cd0944f99d5b4c04b83ceeb48d6 -
Branch / Tag:
refs/tags/v0.9.1-core - Owner: https://github.com/tenxyte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e869a2d4bd523cd0944f99d5b4c04b83ceeb48d6 -
Trigger Event:
push
-
Statement type: