django-auth
SKILL.md
Django Authentication & Permissions
You are a Django authentication expert. Your goal is to help implement secure, maintainable auth systems.
Initial Assessment
Check for project context first:
If .agents/django-project-context.md exists, read it for the existing User model location, auth backend, and permissions approach.
Critical first question: Does this project already have a custom User model?
- If yes: Read it before suggesting changes.
- If no and migrations exist: Explain that adding one now requires careful steps.
- If new project: Always set up a custom User model before first migration.
Custom User Model (Always Do This First)
Do this before any migrate command in a new project. It's very hard to add later.
Option A: AbstractUser (Recommended — extends default User)
# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
"""Custom user model — add fields here as needed."""
email = models.EmailField(unique=True) # Make email unique if needed
bio = models.TextField(blank=True)
avatar = models.ImageField(upload_to='avatars/', blank=True)
# Optional: use email as the login field
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username'] # Required for createsuperuser
def __str__(self):
return self.email
Option B: AbstractBaseUser (Full control — more work)
Use when you need completely custom fields and don't want Django's built-in username/first_name/last_name.
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
class UserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('Email is required')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
return self.create_user(email, password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
Register in Settings
# settings.py
AUTH_USER_MODEL = 'users.User' # Always use this — never import User directly
Always Reference AUTH_USER_MODEL
# In models:
from django.conf import settings
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
# In code (when you need the actual class):
from django.contrib.auth import get_user_model
User = get_user_model()
Django's Permission System
Model-Level Permissions (Built-in)
Django auto-creates these for every model:
app.add_modelnameapp.change_modelnameapp.delete_modelnameapp.view_modelname
Custom Permissions
class Article(models.Model):
class Meta:
permissions = [
('publish_article', 'Can publish articles'),
('feature_article', 'Can feature articles on homepage'),
]
Checking Permissions
# In views (FBV):
from django.contrib.auth.decorators import permission_required
@permission_required('articles.publish_article', raise_exception=True)
def publish_article(request, pk):
...
# In CBV:
from django.contrib.auth.mixins import PermissionRequiredMixin
class PublishArticleView(PermissionRequiredMixin, View):
permission_required = 'articles.publish_article'
# In code:
if request.user.has_perm('articles.publish_article'):
...
# In templates:
{% if perms.articles.publish_article %}
<button>Publish</button>
{% endif %}
Groups
from django.contrib.auth.models import Group, Permission
# Create group with permissions
editors = Group.objects.create(name='Editors')
perm = Permission.objects.get(codename='publish_article')
editors.permissions.add(perm)
# Assign user to group
user.groups.add(editors)
Authentication Backends
Default Session-Based Auth
Works out of the box. No configuration needed.
# views.py
from django.contrib.auth import authenticate, login, logout
def login_view(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
user = authenticate(request, username=email, password=password)
if user:
login(request, user)
return redirect('dashboard')
# Handle invalid credentials
Custom Backend (e.g., email login)
# users/backends.py
from django.contrib.auth import get_user_model
class EmailBackend:
def authenticate(self, request, username=None, password=None):
User = get_user_model()
try:
user = User.objects.get(email=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
User = get_user_model()
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
# settings.py
AUTHENTICATION_BACKENDS = ['users.backends.EmailBackend']
django-allauth (Social + Email Auth)
Setup
pip install django-allauth
# settings.py
INSTALLED_APPS += [
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.google', # Add providers
]
SITE_ID = 1
AUTHENTICATION_BACKENDS = ['allauth.account.auth_backends.AuthenticationBackend']
# allauth settings
ACCOUNT_LOGIN_METHODS = {'email'} # Use email for login
ACCOUNT_SIGNUP_FIELDS = ['email*', 'password1*', 'password2*']
ACCOUNT_EMAIL_VERIFICATION = 'mandatory' # 'optional' or 'none'
LOGIN_REDIRECT_URL = '/dashboard/'
# urls.py
urlpatterns += [path('accounts/', include('allauth.urls'))]
Password Validation
# settings.py
AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 'OPTIONS': {'min_length': 10}},
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
]
Related Skills
- django-drf: JWT and Token authentication for REST APIs
- django-models: Custom User model field design
- django-admin: Register custom User in admin
- django-views: LoginRequiredMixin and PermissionRequiredMixin
Weekly Installs
3
Repository
ristemingov/dja…de-setupFirst Seen
5 days ago
Security Audits
Installed on
cline3
gemini-cli3
github-copilot3
codex3
kimi-cli3
cursor3