Reusable auth + profiles foundations for Django/DRF projects
Project description
jb-drf-auth
Reusable authentication foundations for Django + Django REST Framework projects.
jb-drf-auth provides a clean, extensible base for authentication-related concerns, focused on:
- Abstract user and profile models
- Soft delete using
django-safedelete - Support for multiple profiles per user
- Project-level extensibility (different profile schemas per project)
- Integration with DRF viewsets/serializers
This package is designed to be installed via PyPI and reused across multiple Django projects without duplicating auth logic.
✨ Features
- ✅ Abstract
Userbase compatible with default or custom Django users - ✅ Abstract
Profilebase (one user → many profiles) - ✅ Built-in soft delete via
django-safedelete - ✅ Zero migrations inside the package (migrations live in consumer projects)
- ✅ Dynamic model resolution via Django settings
- ✅ Django 5 compatible
- ✅ DRF serializers, services, and views based on
base_code
📦 Installation
pip install jb-drf-auth
Add jb_drf_auth and rest_framework to INSTALLED_APPS.
⚙️ Settings
Minimal required settings (add to settings.py):
JB_DRF_AUTH_PROFILE_MODEL = "authentication.Profile"
JB_DRF_AUTH_DEVICE_MODEL = "authentication.Device"
JB_DRF_AUTH_OTP_MODEL = "authentication.OtpCode"
JB_DRF_AUTH_EMAIL_LOG_MODEL = "authentication.EmailLog"
JB_DRF_AUTH_FRONTEND_URL = "https://your-frontend"
JB_DRF_AUTH_DEFAULT_FROM_EMAIL = "no-reply@your-domain.com"
Optional:
JB_DRF_AUTH_AUTHENTICATION_TYPE = "email" # "email", "username", "both"
JB_DRF_AUTH_AUTH_SINGLE_SESSION_ON_MOBILE = False
JB_DRF_AUTH_ADMIN_BOOTSTRAP_TOKEN = "super-secret"
JB_DRF_AUTH_PROFILE_PICTURE_UPLOAD_TO = "uploads/users/profile-pictures"
JB_DRF_AUTH_SMS_PROVIDER = "jb_drf_auth.providers.aws_sns.AwsSnsSmsProvider"
JB_DRF_AUTH_SMS_SENDER_ID = "YourBrand"
JB_DRF_AUTH_SMS_TYPE = "Transactional"
JB_DRF_AUTH_SMS_OTP_MESSAGE = "Tu codigo es {code}. Expira en {minutes} minutos." #OTP messages must use 160 GSM-7 characters only (no accents, emojis, or special symbols).
JB_DRF_AUTH_SMS_LOG_MODEL = "authentication.SmsLog"
JB_DRF_AUTH_EMAIL_PROVIDER = "jb_drf_auth.providers.django_email.DjangoEmailProvider"
JB_DRF_AUTH_EMAIL_TEMPLATES = {}
JB_DRF_AUTH_OTP_LENGTH = 6
JB_DRF_AUTH_OTP_TTL_SECONDS = 300
JB_DRF_AUTH_OTP_MAX_ATTEMPTS = 5
JB_DRF_AUTH_OTP_RESEND_COOLDOWN_SECONDS = 60
JB_DRF_AUTH_PHONE_DEFAULT_COUNTRY_CODE = "52" # required only if clients don't send E.164 (+countrycode)
You can also configure everything using a single dict (copy/paste ready):
AUTH_USER_MODEL = "authentication.User"
JB_DRF_AUTH = {
"PROFILE_MODEL": "authentication.Profile",
"DEVICE_MODEL": "authentication.Device",
"OTP_MODEL": "authentication.OtpCode",
"SMS_LOG_MODEL": "authentication.SmsLog",
"EMAIL_LOG_MODEL": "authentication.EmailLog",
"FRONTEND_URL": "https://your-frontend",
"DEFAULT_FROM_EMAIL": "no-reply@your-domain.com",
"AUTHENTICATION_TYPE": "email", # "email", "username", "both"
"CLIENT_CHOICES": ("web", "mobile"),
"AUTH_SINGLE_SESSION_ON_MOBILE": False,
"ADMIN_BOOTSTRAP_TOKEN": "super-secret",
"PROFILE_PICTURE_UPLOAD_TO": "uploads/users/profile-pictures",
"PROFILE_ROLE_CHOICES": (
("USER", "Usuario"),
("COMMERCE", "Comercio"),
("ADMIN", "Admin"),
),
"PROFILE_GENDER_CHOICES": (
("MALE", "Masculino"),
("FEMALE", "Femenino"),
("OTHER", "Otro"),
("PREFER_NOT_TO_SAY", "Prefiero no decirlo"),
),
"DEFAULT_PROFILE_ROLE": "USER",
"PROFILE_ID_CLAIM": "profile_id",
"SMS_PROVIDER": "jb_drf_auth.providers.aws_sns.AwsSnsSmsProvider",
"SMS_SENDER_ID": "YourBrand",
"SMS_TYPE": "Transactional",
"SMS_OTP_MESSAGE": "Tu codigo es {code}. Expira en {minutes} minutos.",
"OTP_LENGTH": 6,
"OTP_TTL_SECONDS": 300,
"OTP_MAX_ATTEMPTS": 5,
"OTP_RESEND_COOLDOWN_SECONDS": 60,
"PHONE_DEFAULT_COUNTRY_CODE": "52",
"PHONE_MIN_LENGTH": 10,
"PHONE_MAX_LENGTH": 15,
"EMAIL_PROVIDER": "jb_drf_auth.providers.django_email.DjangoEmailProvider",
"EMAIL_TEMPLATES": {},
}
Email template example:
JB_DRF_AUTH_EMAIL_TEMPLATES = {
"email_confirmation": {
"subject": "Verifica tu correo",
"text": "Hola {user_email}, verifica tu correo aqui: {verify_url}",
"html": "<p>Hola {user_email},</p><a href=\"{verify_url}\">Verificar</a>",
},
"password_reset": {
"subject": "Restablece tu contrasena",
"text": "Hola {user_email}, restablece tu contrasena: {reset_url}",
"html": "<p>Hola {user_email},</p><a href=\"{reset_url}\">Restablecer</a>",
},
}
🧩 Models
Create concrete models in your project by extending the base classes.
# authentication/models.py
from django.db import models
from jb_drf_auth.models import (
AbstractJbUser,
AbstractJbProfile,
AbstractJbDevice,
AbstractJbEmailLog,
AbstractJbOtpCode,
AbstractJbSmsLog,
)
class User(AbstractJbUser):
pass
class Profile(AbstractJbProfile):
pass
class Device(AbstractJbDevice):
pass
class OtpCode(AbstractJbOtpCode):
pass
class SmsLog(AbstractJbSmsLog):
pass
class EmailLog(AbstractJbEmailLog):
pass
Then set AUTH_USER_MODEL = "authentication.User" and run migrations in your project.
🛣️ URLs
# project/urls.py
from django.urls import include, path
urlpatterns = [
path("auth/", include("jb_drf_auth.urls")),
]
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 jb_drf_auth-0.1.0.tar.gz.
File metadata
- Download URL: jb_drf_auth-0.1.0.tar.gz
- Upload date:
- Size: 22.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
486ed1fd37dbedb902e2501246ff919b2b104b3d36de7d3bee652d0001175f1b
|
|
| MD5 |
eb55f2cc6cc37f1713d93bbb79772cb9
|
|
| BLAKE2b-256 |
a7965185cc940b04fc7cb5035260e86a81dc52122469bfd01cbf3a0105a4ec77
|
Provenance
The following attestation bundles were made for jb_drf_auth-0.1.0.tar.gz:
Publisher:
pypi-publish.yml on joelbarron/jb-drf-auth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jb_drf_auth-0.1.0.tar.gz -
Subject digest:
486ed1fd37dbedb902e2501246ff919b2b104b3d36de7d3bee652d0001175f1b - Sigstore transparency entry: 841096148
- Sigstore integration time:
-
Permalink:
joelbarron/jb-drf-auth@a84064c9117f2ef99d5c4bc4ebe74095b6d38c98 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/joelbarron
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@a84064c9117f2ef99d5c4bc4ebe74095b6d38c98 -
Trigger Event:
release
-
Statement type:
File details
Details for the file jb_drf_auth-0.1.0-py3-none-any.whl.
File metadata
- Download URL: jb_drf_auth-0.1.0-py3-none-any.whl
- Upload date:
- Size: 35.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 |
466f84cb3e2a42e078e776d67042fde539a79d5a7658212a7d368a9261fd74b3
|
|
| MD5 |
cc6411d659acccf3264003c157f507b5
|
|
| BLAKE2b-256 |
d1228a0e45352d5394b5d8c89975c85b801a838552fd49c65a9d7f3ba345312d
|
Provenance
The following attestation bundles were made for jb_drf_auth-0.1.0-py3-none-any.whl:
Publisher:
pypi-publish.yml on joelbarron/jb-drf-auth
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jb_drf_auth-0.1.0-py3-none-any.whl -
Subject digest:
466f84cb3e2a42e078e776d67042fde539a79d5a7658212a7d368a9261fd74b3 - Sigstore transparency entry: 841096161
- Sigstore integration time:
-
Permalink:
joelbarron/jb-drf-auth@a84064c9117f2ef99d5c4bc4ebe74095b6d38c98 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/joelbarron
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@a84064c9117f2ef99d5c4bc4ebe74095b6d38c98 -
Trigger Event:
release
-
Statement type: