Django authentication app with custom user model
Project description
Django Users Authentication 🔐
A powerful Django authentication library that simplifies user management in your Django projects. This library eliminates the need to create separate authentication apps by providing ready-to-use endpoints for user registration, login, logout, and token management (both access and refresh tokens).
✨ Features
- 👤 Custom User Model with email-based authentication
- 🔒 JWT Authentication (access and refresh tokens)
- 🚀 Ready-to-use endpoints for:
- User Registration
- Login
- Logout
- Token Refresh
- ⚙️ Easy integration with existing Django projects
- 🛡️ Built-in security features
🚀 Installation
pip install django-users-auth
📦 Structure
The library consists of two main apps:
1. Users App
Handles all user-related functionality including:
- Custom User Model
- Authentication Views
- JWT Token Management
- User Permissions
Key Files
1. models.py
Defines the custom user model that uses email as the primary identifier.
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.validators import UnicodeUsernameValidator
from .managers import CustomUserManager
from django.db.models.signals import pre_delete
from django.contrib.auth.models import Group as OriginalGroup
from django.dispatch import receiver
import uuid
class User(AbstractUser):
id = models.AutoField(primary_key=True)
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
email = models.EmailField(unique=True)
username = models.CharField(
"username",
max_length=150,
validators=[UnicodeUsernameValidator()],
error_messages={"unique": "Ya existe un usuario con ese nombre de usuario."},
)
groups = models.ManyToManyField(
OriginalGroup,
related_name='custom_user_groups',
blank=True
)
user_permissions = models.ManyToManyField(
'auth.Permission',
related_name='custom_user_permissions',
blank=True
)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = CustomUserManager()
Detalles de la Clase User:
-
Campos:
id: Clave primaria autoincrementaluuid: Identificador único universal, generado automáticamenteemail: Campo único para autenticación del usuariousername: Nombre de usuario con validación Unicodegroups: Relación ManyToMany con grupos personalizadosuser_permissions: Permisos específicos del usuario
-
Características Principales:
- Utiliza UUID para identificación única
- Autenticación basada en email
- Validación personalizada de nombre de usuario
- Relaciones personalizadas de grupos y permisos
- Manejo de señales para eliminación segura
2. serializers.py
Handles data serialization and validation for the REST API.
from rest_framework import serializers
from django.contrib.auth import get_user_model
from django.contrib.auth.password_validation import validate_password
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, validators=[validate_password])
username = serializers.CharField(write_only=True)
uuid = serializers.CharField()
class Meta:
model = get_user_model()
fields = ['username', 'email', 'password', 'uuid']
extra_kwargs = {'password': {'write_only': True}}
def validate(self, data):
if get_user_model().objects.filter(email=data['email']).exists():
raise serializers.ValidationError({"email": ["Ya existe un usuario con ese correo electrónico."]})
return data
def create(self, validated_data):
user = get_user_model().objects.create_user(
username=validated_data['username'],
email=validated_data['email'],
password=validated_data['password']
)
return user
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
token['is_superuser'] = user.is_superuser
token['is_staff'] = user.is_staff
token['user_id'] = user.id
token['uuid'] = str(user.uuid)
return token
Detalles de los Serializadores:
-
UserSerializer:
- Campos:
password: Campo de escritura con validación de contraseñausername: Campo de escritura para nombre de usuariouuid: Identificador únicoemail: Email del usuario
- Métodos:
validate: Verifica la unicidad del emailcreate: Crea un nuevo usuario con datos validados
- Campos:
-
CustomTokenObtainPairSerializer:
- Funcionalidad:
- Extiende TokenObtainPairSerializer
- Añade información adicional al token:
- Estado de superusuario
- Estado de staff
- ID de usuario
- UUID
- Funcionalidad:
3. managers.py
Implements custom user management and JWT authentication logic.
from django.contrib.auth.base_user import BaseUserManager
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.exceptions import InvalidToken, TokenError
from rest_framework.exceptions import AuthenticationFailed
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('The Email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
if not password:
password = BaseUserManager.make_random_password(self)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
return self.create_user(email, password, **extra_fields)
class CustomJWTAuthentication(JWTAuthentication):
def authenticate(self, request):
try:
return super().authenticate(request)
except InvalidToken as e:
if 'refresh' in str(e):
raise AuthenticationFailed('Refresh token is invalid or expired. Please log in again.')
else:
raise AuthenticationFailed('Access token is invalid. Please refresh your token.')
except TokenError as e:
raise AuthenticationFailed(f'Token error: {str(e)}')
Detalles de los Managers:
-
CustomUserManager:
-
**create_user(email, password, extra_fields):
- Crea un usuario normal
- Valida y normaliza el email
- Genera contraseña automática si no se proporciona
- Guarda el usuario en la base de datos
-
**create_superuser(email, password, extra_fields):
- Crea un superusuario
- Establece permisos de staff y superusuario
- Hereda la funcionalidad de create_user
-
-
CustomJWTAuthentication:
- Manejo detallado de errores de token
- Mensajes específicos para tokens inválidos o expirados
- Gestión separada de tokens de acceso y actualización
4. permissions.py
Defines custom permission classes for access control.
from rest_framework import permissions
from rest_framework.permissions import SAFE_METHODS
class IsAuthenticatedAndSelfOrIsStaff(permissions.BasePermission):
def has_permission(self, request, view):
return bool(
request.method in SAFE_METHODS or
request.user and
request.user.is_authenticated
)
def has_object_permission(self, request, view, obj):
return request.user.is_authenticated and (request.user == obj or request.user.is_superuser)
class IsAuthenticatedAndObjUserOrIsStaff(permissions.BasePermission):
def has_permission(self, request, view):
return bool(
request.method in SAFE_METHODS or
request.user and
request.user.is_authenticated
)
def has_object_permission(self, request, view, obj):
return request.user.is_authenticated and (request.user == obj.user or request.user.is_superuser)
Detalles de los Permisos:
-
IsAuthenticatedAndSelfOrIsStaff:
- has_permission:
- Permite métodos seguros (GET, HEAD, OPTIONS)
- Verifica autenticación del usuario
- has_object_permission:
- Permite acceso al propio usuario
- Permite acceso a staff y superusuarios
- has_permission:
-
IsAuthenticatedAndObjUserOrIsStaff:
- Similar al anterior pero para objetos relacionados
- Verifica la relación usuario-objeto
- Control granular de permisos a nivel de objeto
5. viewsets.py
Implements ViewSets for handling user-related operations.
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework_simplejwt.views import TokenObtainPairView
from .models import User
from .serializers import UserSerializer, CustomTokenObtainPairSerializer
from .permissions import IsAuthenticatedAndObjUserOrIsStaff
class CustomTokenObtainPairView(TokenObtainPairView):
serializer_class = CustomTokenObtainPairSerializer
class UserViewSet(viewsets.ModelViewSet):
serializer_class = UserSerializer
permission_classes = [IsAuthenticatedAndObjUserOrIsStaff]
http_method_names = ['get', 'options', 'head']
queryset = User.objects.all()
def get_queryset(self):
if self.request.user.is_superuser:
return User.objects.all()
elif self.request.user.is_staff:
return User.objects.all()
elif self.request.user.is_authenticated:
return User.objects.filter(pk=self.request.user.pk)
else:
raise exceptions.PermissionDenied('Forbidden')
class RegisterViewSet(viewsets.ViewSet):
permission_classes = [AllowAny]
def create(self, request):
serializer = UserSerializer(data=request.data)
if serializer.validate(request.data):
user = serializer.create(request.data)
return Response({'status': '201'}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Detalles de los ViewSets:
-
CustomTokenObtainPairView:
- Personaliza la generación de tokens JWT
- Utiliza CustomTokenObtainPairSerializer
-
UserViewSet:
- Configuración:
- Métodos permitidos: GET, OPTIONS, HEAD
- Permisos basados en roles
- get_queryset:
- Filtra usuarios según permisos
- Acceso total para superusuarios y staff
- Acceso limitado para usuarios normales
- Configuración:
-
RegisterViewSet:
- Permite registro público (AllowAny)
- Validación completa de datos
- Creación segura de usuarios
6. admin.py
Configures the Django admin interface for user management.
from django.contrib import admin
from .models import User, Group
from django.contrib.auth.models import Group as OriginalGroup
from django.contrib import auth
@admin.register(User)
class UserAdmin(auth.admin.UserAdmin):
list_display = ('email','is_active', 'is_staff', 'uuid')
def get_readonly_fields(self, request, obj=None):
if request.user.is_superuser:
return ()
if request.user.is_staff:
return ('is_staff', 'groups', 'user_permissions')
return (auth.admin.UserAdmin.fields)
admin.site.register(Group)
admin.site.unregister(OriginalGroup)
Detalles de la Configuración Admin:
-
UserAdmin:
- Visualización:
- Muestra email, estado activo, estado staff y UUID
- Control de Acceso:
- Superusuarios: acceso total
- Staff: campos restringidos
- Usuarios normales: solo lectura
- Visualización:
-
Gestión de Grupos:
- Registro personalizado de grupos
- Integración con modelo de usuario personalizado
- Desregistro del modelo Group original
2. Base App
The Base app provides core functionality and base models for the authentication system. It serves as the foundation for the Users app and includes essential configurations.
🔧 Complete Configuration
To fully integrate the authentication system, add these settings to your settings.py:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_simplejwt',
'users',
'base',
]
# User model configuration
AUTH_USER_MODEL = 'users.User'
# REST Framework settings
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'users.managers.CustomJWTAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
# JWT settings
from datetime import timedelta
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
}
🛣️ API Endpoints Reference
Authentication Endpoints
1. User Registration
POST /api/auth/register/
Content-Type: application/json
{
"email": "user@example.com",
"username": "username",
"password": "secure_password123"
}
Response: 201 Created
{
"status": "201"
}
2. User Login
POST /api/auth/login/
Content-Type: application/json
{
"email": "user@example.com",
"password": "secure_password123"
}
Response: 200 OK
{
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"user_id": 1,
"is_superuser": false,
"uuid": "550e8400-e29b-41d4-a716-446655440000"
}
3. Token Refresh
POST /api/auth/token/refresh/
Content-Type: application/json
{
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}
Response: 200 OK
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}
🔒 Security Features
-
Email-Based Authentication
- Secure email validation
- Unique email constraint
- Custom user manager for email handling
-
Password Security
- Django's password validation
- Secure password hashing
- Password strength requirements
-
JWT Token Security
- Access and refresh token mechanism
- Token expiration and rotation
- Custom token payload
- Token blacklisting
-
Permission System
- Role-based access control
- Object-level permissions
- Staff and superuser privileges
- Custom permission classes
-
Admin Security
- Restricted admin access
- Role-based field restrictions
- Secure group management
🚀 Best Practices
-
Token Management
- Store tokens securely
- Implement token refresh mechanism
- Handle token expiration gracefully
-
Error Handling
- Implement proper error responses
- Validate input data
- Handle edge cases
-
Security
- Use HTTPS in production
- Implement rate limiting
- Follow security headers best practices
-
User Experience
- Implement proper validation messages
- Handle registration/login flows smoothly
- Provide clear error messages
2. Base App
Provides core functionality and base models for the authentication system. The Base app includes essential utilities that enhance the overall functionality of the authentication system.
Key Files
1. managers.py
Implements custom pagination functionality for handling large datasets efficiently.
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
class CustomPagination(PageNumberPagination):
page_size = 250
page_size_query_param = 'page_size'
def get_paginated_response(self, data):
return Response({
'total_pages': self.page.paginator.num_pages,
'total_items': self.page.paginator.count,
'current_page': self.page.number,
'next': self.get_next_link(),
'previous': self.get_previous_link(),
'results': data
})
Details of CustomPagination:
-
Configuration:
- Default page size: 250 items
- Configurable page size via query parameter
-
Enhanced Response Format:
total_pages: Total number of available pagestotal_items: Total count of items in the datasetcurrent_page: Current page numbernext: URL for the next pageprevious: URL for the previous pageresults: Paginated data
-
Usage Example:
from base.managers import CustomPagination
class YourViewSet(viewsets.ModelViewSet):
pagination_class = CustomPagination
🔧 Configuration
Add the following to your settings.py:
INSTALLED_APPS = [
...
'users',
'base',
]
# JWT Authentication settings
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'users.managers.CustomJWTAuthentication',
]
}
🛣️ Available Endpoints
POST /api/auth/register/- User registrationPOST /api/auth/login/- User loginPOST /api/auth/logout/- User logoutPOST /api/auth/token/refresh/- Refresh access token
💻 Usage Example
# Registration
POST /api/auth/register/
{
"email": "user@example.com",
"password": "secure_password"
}
# Login
POST /api/auth/login/
{
"email": "user@example.com",
"password": "secure_password"
}
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
📧 Contact
Martin - vazquezmartin1240@gmail.com
Project Link: https://github.com/Vazquez1240/authentication-django
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 django_users_auth-2.4.2b0.tar.gz.
File metadata
- Download URL: django_users_auth-2.4.2b0.tar.gz
- Upload date:
- Size: 21.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 |
ce9fb3463473806b8934e72700d023c39ca5ef295d3af629b87193876a5f920f
|
|
| MD5 |
7b624935b29acf1d44d9e966ccca714a
|
|
| BLAKE2b-256 |
a17cf1f1d3d0649e38ae99ba447aa701c1abe302856ced7d0eb7298eea88ccfd
|
File details
Details for the file django_users_auth-2.4.2b0-py3-none-any.whl.
File metadata
- Download URL: django_users_auth-2.4.2b0-py3-none-any.whl
- Upload date:
- Size: 20.6 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 |
39124c4b06e1a716dc68504e13445f0dcfaf381a8da40f180a1cae4fdccbf2d9
|
|
| MD5 |
f9bc6a9cd2dacf6878b6506902cdbb3b
|
|
| BLAKE2b-256 |
d844763db06cd89d842344d87329fe308db2175359aa5f81e64679685dd32224
|