A modern authentication and user management package for Django (Clerk-style)
Project description
Authera — Django Authentication (Clerk‑style)
Authera is a modern authentication and user management package for Django that enables Clerk‑style, step‑based auth flows using Django REST Framework and SimpleJWT.
Key features
- Pluggable, multi‑step authentication scenarios
- First‑class Django REST Framework endpoints
- JWT issuance and refresh via djangorestframework‑simplejwt
- Stateless step tracking using Django cache
- Minimal, extensible building blocks for custom auth UX
Requirements
- Python >= 3.9
- Django >= 4.2
- djangorestframework >= 3.15
- djangorestframework-simplejwt >= 5.3.0
Installation
pip install authera
Or install from source in editable mode:
pip install -e .
Quickstart
- Add apps to
INSTALLED_APPS:
INSTALLED_APPS = [
"django.contrib.auth",
"django.contrib.contenttypes",
"rest_framework",
"rest_framework_simplejwt",
"authera",
]
- Configure DRF + SimpleJWT (recommended):
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
}
from datetime import timedelta
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=15),
"REFRESH_TOKEN_LIFETIME": timedelta(days=7),
}
- Define your user step scenarios:
Authera ships with a simple username/password scenario you can start with. You can add more scenarios or implement your own later.
# settings.py
from authera.scenario import UsernamePasswordScenario
USER_STEP_SCENARIO = [
# name, key, and TTL (seconds) for the next‑step state per user
UsernamePasswordScenario(
name="Username & Password",
key="username-password",
each_user_TTL=300,
),
]
- Wire up URLs:
# urls.py
from django.urls import path, include
urlpatterns = [
path("auth/", include("authera.urls")),
]
Available endpoints
Base path assumes auth/ as shown above.
- GET
auth/options/- Returns the available scenarios and their JSON Schemas for client‑side validation and rendering.
- POST
auth/validate/<scenario_key>- Validates user input for the given scenario step. If it is the final step, returns tokens and user info. Otherwise returns a signed payload and
user_id, and advances the user to the next step.
- Validates user input for the given scenario step. If it is the final step, returns tokens and user info. Otherwise returns a signed payload and
- POST
auth/refresh/- Exchanges a valid refresh token for new access and refresh tokens.
Request/response examples
- Get available options (schemas):
curl -X GET http://localhost:8000/auth/options/
Example response:
{
"username-password": {
"type": "object",
"properties": {
"username": { "type": "string", "minLength": 3, "maxLength": 255 },
"password": { "type": "string", "minLength": 8, "maxLength": 255 }
},
"required": ["username", "password"]
}
}
- Validate a step (username‑password):
curl -X POST http://localhost:8000/auth/validate/username-password \
-H "Content-Type: application/json" \
-d '{
"options": { "username": "alice", "password": "S3cretPass!" }
}'
If this is the final step, you’ll receive tokens and user info:
{
"access_token": "<jwt>",
"refresh_token": "<jwt>",
"token_type": "Bearer",
"expires_in": 900,
"user": {
"id": 1,
"username": "alice",
"permits": ["staff", "editor"]
}
}
- Refresh tokens:
curl -X POST http://localhost:8000/auth/refresh/ \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "<jwt>"
}'
Response:
{
"access_token": "<new_access_jwt>",
"refresh_token": "<new_refresh_jwt>",
"token_type": "Bearer",
"expires_in": 900
}
Extending: create a custom scenario
Implement your own step by subclassing BaseScenario and adding it to USER_STEP_SCENARIO.
from rest_framework.response import Response
from authera.utils import BaseScenario
class EmailOtpScenario(BaseScenario):
schema = {
"type": "object",
"properties": { "email": { "type": "string", "format": "email" }, "otp": { "type": "string" } },
"required": ["email", "otp"]
}
def __init__(self):
super().__init__(name="Email OTP", key="email-otp", each_user_TTL=300)
def validate(self, user_payload, scenario_options) -> Response:
# Validate OTP for the provided email; return 200 to advance, otherwise non‑200
return Response()
def get_user(self, user_id, options):
# Return a Django user instance when this is the last step
...
Security notes
- Always use HTTPS in production.
- Configure reasonable lifetimes for access and refresh tokens.
- Consider rotating refresh tokens and revocation strategies depending on risk profile.
- Ensure cache backend is correctly configured for step‑state tracking.
Development
Run a local Django project that includes authera, then exercise the endpoints with the examples above.
Contributing
Issues and PRs are welcome. Please open an issue to discuss substantial changes first.
License
MIT © Algonouir
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
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 authera-0.1.0.tar.gz.
File metadata
- Download URL: authera-0.1.0.tar.gz
- Upload date:
- Size: 20.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d939d595c38dc5511b6e23389fb325a14a2679b0a173b1cc7abd9bf22a000869
|
|
| MD5 |
0514118eeb7f0b43884e2b1987c56f42
|
|
| BLAKE2b-256 |
db06b4dcd89a3a6cf02897a020aae5dd0e56fbd7f4af8b8b89c1734264912316
|
File details
Details for the file authera-0.1.0-py3-none-any.whl.
File metadata
- Download URL: authera-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
04e0330474771a59f26c5caf0ab95a81901e714b26ba839667b159ad793bd2b8
|
|
| MD5 |
c4fb0e16dee860f56821c0395036710f
|
|
| BLAKE2b-256 |
0161a9c13ed9318605807cd9f6434781b2f8a6a883eec24721f508444895a9f3
|