Django Authentication & Permissions
Django ships a complete authentication system in django.contrib.auth: user accounts, secure password hashing, session-based login and logout, password reset flows, and a permissions system with groups. Combined with Django's CSRF protection and secure session cookies, it gives most web applications solid authentication out of the box, with no third-party service required.
The most important decision comes on day one: use a custom user model. Changing the user model after the first migration is painful. Beyond that, the work is mostly configuration: choosing hashers, setting cookie security, adding social login or SSO if needed, and modeling permissions that match your domain.
TL;DR
- Start every project with a custom user model (
AUTH_USER_MODEL), even if it's initially identical to the default. - Django uses server-side sessions with a secure cookie;
login()/logout()manage them, andrequest.useris available everywhere. - Passwords are hashed (PBKDF2 by default; Argon2 recommended), with configurable password validators.
- Permissions: auto-created model permissions (
add,change,delete,view), custom permissions, and groups. Check them withuser.has_perm(). - Protect views with
@login_required,LoginRequiredMixin, andPermissionRequiredMixin, or theLoginRequiredMiddleware(Django 5.1+). - Add social login, MFA, and email verification with django-allauth; for enterprise SSO, use OIDC or SAML libraries.
Quick Example
A custom user model using email as the login identifier:
Core Concepts
The User Model
The default User has username, email, names, password, is_active, is_staff, is_superuser, groups, and permissions. A custom user model (subclassing AbstractUser, or AbstractBaseUser for full control) lets you use email login, add fields, and change behavior later without a painful migration. Always refer to the user model via settings.AUTH_USER_MODEL in ForeignKeys and get_user_model() in code. Store profile data that isn't needed for authentication in a separate one-to-one Profile model if the user table would otherwise grow large.
Sessions and Login
authenticate(request, username=..., password=...) checks credentials against the configured authentication backends. login(request, user) stores the user ID in the session and rotates the session key, preventing session fixation. The session cookie is a random ID, and session data lives server-side (database, cache, or signed cookies). AuthenticationMiddleware attaches request.user, an AnonymousUser when not logged in.
Password Hashing
Passwords are stored as algorithm$iterations$salt$hash. When you change PASSWORD_HASHERS, Django upgrades a user's hash transparently on their next login. Argon2 is the recommended algorithm, and bcrypt and scrypt are supported. See password security.
Permissions and Groups
- Model permissions (
app.add_model,change,delete,view) are created automatically for each model. - Custom permissions go in
Meta.permissions = [("approve_refund", "Can approve refunds")]. - Groups bundle permissions, like "Support Agents" or "Finance". Assign users to groups instead of individual permissions.
user.has_perm("billing.approve_refund")checks; superusers pass every check.
Django's built-in permissions are model-level ("can change any order"). For object-level rules ("can change this order"), use django-guardian or django-rules, or write explicit checks in views and querysets.
Authentication Backends
AUTHENTICATION_BACKENDS lists classes that verify credentials: ModelBackend for passwords, plus backends for LDAP, remote-user headers, or social providers. Custom backends implement authenticate() and get_user().
Beyond Username and Password
See MFA and OAuth for the underlying protocols.
Best Practices
Create the Custom User Model Before the First Migration
Even class User(AbstractUser): pass gives you room to change later. Swapping user models mid-project requires hand-crafted migrations across every app referencing users.
Harden Session and Cookie Settings
In production: SESSION_COOKIE_SECURE, CSRF_COOKIE_SECURE, SECURE_HSTS_SECONDS, and SECURE_SSL_REDIRECT, with SESSION_COOKIE_SAMESITE = "Lax" (the default). Run python manage.py check --deploy to catch missing settings. See security headers.
Rate-Limit Login and Reset Endpoints
Django doesn't throttle login attempts by default. Add rate limiting (django-axes, django-ratelimit, or your reverse proxy) to slow credential stuffing and brute force.
Model Authorization Around Roles and Ownership
Use groups for roles, and restrict querysets by ownership (Order.objects.filter(customer__user=request.user)) so users can't reach others' data through any view. Test authorization for every sensitive endpoint.
Common Mistakes
Referencing auth.User Directly
Checking Permissions Only in Templates
Hiding a button with {% if perms.billing.approve_refund %} doesn't stop anyone from posting to the endpoint. Enforce permissions in views and APIs, and use templates only for presentation.
Storing Sensitive Data in Signed-Cookie Sessions
signed_cookies session storage is tamper-proof but not encrypted: clients can read its contents. Keep sensitive data in database- or cache-backed sessions.
FAQ
Should I use a custom user model?
Yes, always, for new projects. Django's documentation strongly recommends it. It costs nothing up front and avoids a difficult migration if you later need email login or extra fields.
How do I log in with email instead of username?
Use a custom user model with USERNAME_FIELD = "email", a unique email field, and a custom manager, as in the example above. django-allauth also supports email-only login with verification flows.
Does Django support two-factor authentication?
Not in core. Add it with django-allauth's MFA module (TOTP, WebAuthn, recovery codes) or django-otp. Protect admin logins especially, for example by requiring MFA for staff accounts.
Sessions or JWT for my API?
For first-party browser apps on the same site, Django sessions with CSRF protection are simpler and safer: HttpOnly cookies are inaccessible to JavaScript. Use tokens or JWT for third-party clients, mobile apps, or cross-domain APIs. See JWT.
Related Topics
- Django — The framework overview
- Authentication — Authentication concepts in general
- Django REST Framework — API authentication and permissions
- Password Security — Hashing and password policies
- SSO — Enterprise single sign-on
- MFA — Multi-factor authentication