Framework-agnostic Python authentication — JWT, RBAC, 2FA, Magic Links, Passkeys, Social Login, B2B Organizations, multi-tenant support. Works with Django, FastAPI, and more.
Project description
Tenxyte Auth
Framework-Agnostic Python Authentication in minutes — JWT, RBAC, 2FA, Magic Links, Passkeys, Social Login, Breach Check, Organizations (B2B), multi-application support.
Quickstart — 2 minutes to your first API call
1. Install
pip install tenxyte
Requirements: Python 3.10+, Django 4.2+ or FastAPI 0.135+
2. Configure
# settings.py — add at the very bottom
import tenxyte
tenxyte.setup(globals()) # auto-injects INSTALLED_APPS, AUTH_USER_MODEL, REST_FRAMEWORK, MIDDLEWARE
# urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('api/auth/', include('tenxyte.urls')),
]
3. Run
python manage.py tenxyte_quickstart # migrate + seed roles + create Application
python manage.py runserver
4. First API call
# Register — use the credentials displayed by tenxyte_quickstart
curl -X POST http://localhost:8000/api/v1/auth/register/ \
-H "Content-Type: application/json" \
-H "X-Access-Key: <your-access-key>" -H "X-Access-Secret: <your-access-secret>" \
-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 "Content-Type: application/json" \
-H "X-Access-Key: <your-access-key>" -H "X-Access-Secret: <your-access-secret>" \
-d '{"email": "user@example.com", "password": "SecureP@ss1!"}'
# Authenticated request
curl http://localhost:8000/api/v1/auth/me/ \
-H "X-Access-Key: <your-access-key>" -H "X-Access-Secret: <your-access-secret>" \
-H "Authorization: Bearer <access_token>"
⚠️ In
DEBUG=True, Tenxyte auto-generates an ephemeral JWT secret key (invalidated on restart) and applies relaxed security limits.X-Access-Key/X-Access-Secretheaders are still required unless you explicitly setTENXYTE_APPLICATION_AUTH_ENABLED = False.
💡 Include
"login": truein the register request to receive JWT tokens in the response immediately.
That's it — you have a fully featured auth backend running.
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)
- 9 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
Installation Options
pip install tenxyte # Includes Django adapter (backward compatible)
pip install tenxyte[core] # Core only — no framework, bring your own
pip install tenxyte[fastapi] # FastAPI adapter + Core
# Optional Extras (work with any adapter)
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[webauthn] # Passkeys / FIDO2
pip install tenxyte[all] # Everything included
Production Setup
# 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
Endpoints Overview
Routes require
X-Access-KeyandX-Access-Secretheaders by default. To disable this check in development, setTENXYTE_APPLICATION_AUTH_ENABLED = False(forbidden in production).
| 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) |
For complete examples with full request/response bodies, see endpoints.md.
Interactive Documentation
Add these routes to your urls.py for Swagger UI and ReDoc:
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView, SpectacularRedocView
from tenxyte.conf import auth_settings
api_prefix = auth_settings.API_PREFIX.strip('/')
urlpatterns += [
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'),
]
- Postman Collection — Ready-to-use collection
📚 Documentation
📖 Developer Guides
- Quickstart - Get started in 2 minutes with Django
- FastAPI Quickstart - Get started with FastAPI
- Settings Reference - All 115+ configuration options
- API Endpoints - Full endpoint reference with examples
- Admin Accounts - Manage Superusers and RBAC Admins
- Applications Guide - Manage API clients and credentials
- RBAC Guide - Roles, permissions, and decorators
- Security Guide - Security features and best practices
- Organizations Guide - B2B multi-tenant setup
- AIRS Guide - AI Responsibility & Security
- Migration Guide - Migration from dj-rest-auth, simplejwt
📦 SDK Integration (JavaScript / TypeScript)
- JavaScript SDK Overview - Packages, installation, configuration, error handling
- @tenxyte/core Guide - Framework-agnostic SDK — all 10 modules, cookie mode, PKCE, events
- @tenxyte/react Guide - React hooks, TenxyteProvider, SPA examples
- @tenxyte/vue Guide - Vue 3 composables, plugin setup, SPA examples
🔧 Technical Documentation
- Architecture Guide - Core & Adapters (Hexagonal) architecture
- Async Guide - Async/await patterns and best practices
- Task Service - Background job processing
- Custom Adapters Guide - Creating custom adapters
- Schemas Reference - Reusable schema components
- Testing Guide - Testing strategies and examples
- Periodic Tasks - Scheduled maintenance and cleanup tasks
- Troubleshooting - Common issues and solutions
- Contributing - How to contribute to Tenxyte
Architecture: Core & Adapters
Tenxyte is built around a Framework-Agnostic Core utilizing a Ports and Adapters (Hexagonal) architecture.
- Core: Contains pure Python authentication, JWT, and RBAC logic (zero framework dependencies).
- Ports: Defines abstract interfaces for external operations (e.g., Repositories, EmailServices, CacheServices).
- Adapters: Concrete implementations tailored to frameworks (Django, FastAPI) or libraries.
This design guarantees that existing Django deployments run with zero breaking changes, while natively opening support for modern async frameworks like FastAPI.
Read more in our detailed Architecture Guide.
Supported Databases
- ✅ SQLite — development
- ✅ PostgreSQL — recommended for production
- ✅ MySQL/MariaDB
- ✅ MongoDB — via
django-mongodb-backend(see quickstart.md for configuration)
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.
Creating Custom Framework Adapters
Because Tenxyte is framework-agnostic, you can write your own Database adapters, Cache adapters, or Email adapters using the core Ports. See the Custom Adapters Guide for detailed instructions on extending the core.
Configuration Reference
All 115+ settings documented in 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
Periodic Maintenance
Tenxyte requires periodic tasks (token cleanup, OTP purge, audit log rotation) to maintain performance and security. See the Periodic Tasks Guide for full configuration with Celery Beat or cron.
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/integration/django/multidb/ -o "DJANGO_SETTINGS_MODULE=tests.integration.django.multidb.settings_sqlite"
pytest tests/integration/django/multidb/ -o "DJANGO_SETTINGS_MODULE=tests.integration.django.multidb.settings_pgsql"
pytest tests/integration/django/multidb/ -o "DJANGO_SETTINGS_MODULE=tests.integration.django.multidb.settings_mysql"
pytest tests/integration/django/multidb/ -o "DJANGO_SETTINGS_MODULE=tests.integration.django.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}. See quickstart.md.
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.
For more solutions, see troubleshooting.md.
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.4.tar.gz.
File metadata
- Download URL: tenxyte-0.9.4.tar.gz
- Upload date:
- Size: 900.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a48f703430571e2bf702055016453a4b9d2ce832ecaa75309cc2d4962b45a74f
|
|
| MD5 |
52eeb66c633884d262bb330c80733278
|
|
| BLAKE2b-256 |
43cfb9a7286be7a4b355a488a0a53bc441c46777284ab67454137055be642c69
|
Provenance
The following attestation bundles were made for tenxyte-0.9.4.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.4.tar.gz -
Subject digest:
a48f703430571e2bf702055016453a4b9d2ce832ecaa75309cc2d4962b45a74f - Sigstore transparency entry: 1184278835
- Sigstore integration time:
-
Permalink:
tenxyte/tenxyte@d5e899d66bb308bbc8b629d4c3562928786b5845 -
Branch / Tag:
refs/tags/v0.9.4-core - Owner: https://github.com/tenxyte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d5e899d66bb308bbc8b629d4c3562928786b5845 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tenxyte-0.9.4-py3-none-any.whl.
File metadata
- Download URL: tenxyte-0.9.4-py3-none-any.whl
- Upload date:
- Size: 318.0 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 |
c84f9d35373859af6cddcba6a6a4609517e510f3a647f81263b7dfb233de9c5a
|
|
| MD5 |
a81b54e303fd6e54ec8f862f3156fcba
|
|
| BLAKE2b-256 |
c70b65b6ea86600cfb25291284e9c01488f61a83f1c00b31c5115c77451a5414
|
Provenance
The following attestation bundles were made for tenxyte-0.9.4-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.4-py3-none-any.whl -
Subject digest:
c84f9d35373859af6cddcba6a6a4609517e510f3a647f81263b7dfb233de9c5a - Sigstore transparency entry: 1184278923
- Sigstore integration time:
-
Permalink:
tenxyte/tenxyte@d5e899d66bb308bbc8b629d4c3562928786b5845 -
Branch / Tag:
refs/tags/v0.9.4-core - Owner: https://github.com/tenxyte
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d5e899d66bb308bbc8b629d4c3562928786b5845 -
Trigger Event:
push
-
Statement type: