A reusable Django application for identity and access management —
installed into your project, not cloned as one.
Read the API contract »
·
Report Bug
·
Request Feature
Table of Contents
A Django app that handles accounts, credentials and personal data, extracted from a production system so it can be dropped into another one.
This repository is not a project you run. There is no manage.py, no
settings module and no compose file. It is the users package plus the tests
that prove it works, meant to be installed into a host project — for example
Django-Pro-Template, which
is the scaffold it is developed against.
What it gives you:
- JWT stateless authentication — token rotation and blacklisting.
- TOTP two-factor — enrolment with recovery codes, and anti-replay that holds across workers.
- Step-up authentication — sensitive writes and irreversible deletion require recent re-authentication, for session and bearer-token clients alike.
- Encrypted personal data at rest — Fernet encryption with HMAC blind indexes, so encrypted fields stay searchable by exact match.
- GDPR anonymisation — irreversible erasure layered on soft deletion, with an append-only audit trail.
- Brute-force protection —
django-axeslockout that covers re-authentication, not only login. - Password strength — a 12-character minimum, complexity rules, and rejection of passwords found in public breach corpora.
Nine endpoints, each one specified in
USERS_CONTRACT.md with its fields, status
codes and permission gates.
Verified against Django 5.2 LTS and 6.0, at both ends of the supported range.
Important
This app ships a custom AUTH_USER_MODEL. Django allows that to be set only
before the first migration, so it goes into a new project — it cannot be
added to one that already has auth data.
Not published to PyPI. Vendor the users/ package into your project — copy it,
or add this repository as a submodule and symlink the package — then install
the dependencies it declares:
git clone https://github.com/GstMirabal/Django-Users-App.git /tmp/users-app
cp -r /tmp/users-app/users your-project/
pip install -r /tmp/users-app/requirements.txtrequirements.txt lists only what the app itself imports. Your database
driver, web server and static-file handling stay your project's choice.
INSTALLED_APPS = [
# ...
"rest_framework",
"rest_framework_simplejwt",
"rest_framework_simplejwt.token_blacklist",
"axes",
"users",
]
AUTH_USER_MODEL = "users.User"# urls.py
urlpatterns = [
path("api/v1/users/", include("users.urls")),
]Five requirements, listed in full under Host requirements in the contract:
| Setting | Why |
|---|---|
MASTER_KEY |
Fernet key encrypting all personal data. |
ENCRYPTION_PEPPER |
Keys the blind indexes that keep encrypted fields searchable. |
| A cache shared across workers | TOTP anti-replay and step-up grants. On a per-process backend both fail silently under more than one worker. |
AXES_USERNAME_FORM_FIELD = "username" |
This app logs in by email; without this, django-axes records failed logins against nobody and lockout degrades from per-account to per-IP. |
A receiver for verification_code_issued |
The app issues verification codes and does not send them. Without a receiver, an account can never be verified. |
The contract also lists the commands that generate the two keys, and what rotating them costs.
python manage.py migrateThe suite runs against tests_harness/, a minimal stand-in host, so no
database or cache service is needed.
python3 -m venv venv && source venv/bin/activate
pip install -r requirements-dev.txt
pytest -q # 60 tests, in-RAM SQLite
ruff check .The harness deliberately leaves STEP_UP_WINDOW_SECONDS and
VERIFICATION_OTP_TTL_MINUTES unset, so every run re-proves that a host is not
obliged to declare them.
| Document | What it answers |
|---|---|
USERS_CONTRACT.md |
What each endpoint accepts and returns, and what a host must provide. |
USERS_BLUEPRINT.md |
How the identity domain is built. |
USERS_CUSTOMIZATION_GUIDE.md |
Which parts are the identity core and which extras you can strip. |
docs/decisions/ |
Why each architectural choice was made, and what it cost. |
GLOBAL_ROADMAP.md |
What is known to be missing. Including the gaps. |
Contributions are welcome. See CONTRIBUTING.md for the workflow, and in particular for the trap that has already cost this repository two blocking defects: the test harness hides host requirements by being helpful.
One rule worth repeating here: a bugfix should come with a test checked to fail without the fix, not only to pass with it. Several defects in this repository's history passed that second test while the first would have caught them.
Security problems go through private advisories, never a public issue. That file also lists the limitations that are known and deliberate — chiefly that there is no key rotation path — so they need not be reported again.
Licensed under the MIT License. See LICENSE.txt for more information.
Gustavo Mirabal Suarez - gst.mirabal@gmail.com
- LinkedIn: @Gustavo-Mirabal
- GitHub: @GstMirabal
- Twitter: @GstMirabal
Project Link: https://github.com/GstMirabal/Django-Users-App