Authentication in Django: Login, Logout, Register
Django comes with a robust, battle-tested authentication system that handles user accounts, groups, permissions, and cookie-based user sessions. Whether you’re building a simple website with login/logout capabilities or a complex application with multi-factor authentication, social logins, and API token-based access, Django’s authentication framework has you covered. In this article, we’ll explore everything you need to know about authentication in Django, from the basics of the built‑in User model to advanced topics like custom backends and integrating third‑party authentication.
1. Introduction to Django’s Authentication System
Django’s authentication system is one of its most celebrated features. It provides:
- A fully functional User model (django.contrib.auth.models.User).
- Authentication views and URLs for login, logout, password change, and password reset.
- A permissions framework integrated into both views and the ORM.
- Support for extensibility via custom user models and authentication backends.
By leveraging these built‑in components, you can avoid reinventing the wheel and focus on building the unique features of your application.
2. The Built‑in User Model
At the core of Django’s authentication lies the User model, located in django.contrib.auth.models. It represents a user account and houses fields for username, email, password hash, and more.
2.1 Fields and Methods
Key fields:
- username: Unique identifier (up to 150 characters).
- password: Hashed password (using PBKDF2 by default).
- email: Email address (optional by default).
- first_name, last_name: Optional personal details.
- is_staff, is_active, is_superuser: Flags for admin access and status.
- date_joined, last_login: Timestamps for auditing.
Important methods:
- set_password(raw_password): Hashes and sets the password.
- check_password(raw_password): Validates a raw password.
- get_full_name(), get_short_name(): Utility name methods.
Example of creating a user:
from django.contrib.auth.models import User
user = User.objects.create_user(
username='johndoe',
email='john@example.com',
password='s3cr3t!'
)
user.first_name = 'John'
user.last_name = 'Doe'
user.save()2.2 User Creation and Management
Apart from create_user, there’s also create_superuser:
User.objects.create_superuser(
username='admin',
email='admin@example.com',
password='adm1nP@ss'
)The Django admin offers a user-friendly interface for managing users, groups, and permissions. Simply ensure django.contrib.admin is enabled in INSTALLED_APPS, then navigate to /admin/.
3. Authentication Views and Templates
Django provides class‑based views for authentication in django.contrib.auth.views. To use them:
- Include URLs in your urls.py:
from django.urls import path from django.contrib.auth import views as auth_views urlpatterns = [ path('login/', auth_views.LoginView.as_view(), name='login'), path('logout/', auth_views.LogoutView.as_view(), name='logout'), path('password_change/', auth_views.PasswordChangeView.as_view(), name='password_change'), path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(), name='password_change_done'), path('password_reset/', auth_views.PasswordResetView.as_view(), name='password_reset'), path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'), path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'), path('reset/done/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'), ]- Create templates matching their default names (e.g., registration/login.html, registration/password_reset_form.html, etc.).
3.1 LoginView and LogoutView
- LoginView: Renders a form to capture username and password, handles authentication, and redirects on success.
- LogoutView: Invalidates the user session and redirects to a defined URL.
Example settings in settings.py:
LOGIN_URL = 'login' LOGIN_REDIRECT_URL = 'dashboard' LOGOUT_REDIRECT_URL = 'home'
3.2 Password Change and Reset
- PasswordChangeView: Lets a logged‑in user change their password.
- PasswordResetView: Sends an email with a password reset link.
- PasswordResetConfirmView: Allows setting a new password via the tokenized link.
Ensure email backend configuration (e.g., SMTP settings) in settings.py:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.example.com' EMAIL_PORT = 587 EMAIL_HOST_USER = 'noreply@example.com' EMAIL_HOST_PASSWORD = 'emailpassword' EMAIL_USE_TLS = True DEFAULT_FROM_EMAIL = 'noreply@example.com'
4. Protecting Views: Decorators and Mixins
4.1 @login_required Decorator
To restrict access to logged‑in users:
from django.contrib.auth.decorators import login_required
@login_required
def profile(request):
# Only authenticated users can access
return render(request, 'profile.html')4.2 AccessMixin and LoginRequiredMixin
For class‑based views:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView
class DashboardView(LoginRequiredMixin, TemplateView):
template_name = 'dashboard.html'
login_url = '/login/'
redirect_field_name = 'next'PermissionRequiredMixin can enforce specific permissions:
from django.contrib.auth.mixins import PermissionRequiredMixin
class OrderAdminView(PermissionRequiredMixin, ListView):
model = Order
permission_required = 'orders.change_order'5. Customizing the User Model
Outgrowing the default User model is common when you need additional fields or a different authentication key. Django supports two primary approaches.
5.1 Extending AbstractUser
You inherit from AbstractUser and add fields:
# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
bio = models.TextField(blank=True)
birth_date = models.DateField(null=True, blank=True)Update settings.py:
AUTH_USER_MODEL = 'accounts.CustomUser'
5.2 Swapping to AbstractBaseUser
For full control, subclass AbstractBaseUser and implement required methods:
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.db import models
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('Email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
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)
return self.create_user(email, password, **extra_fields)
class MyUser(AbstractBaseUser):
email = models.EmailField(unique=True)
full_name = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['full_name']5.3 Updating Settings and Forms
- Set AUTH_USER_MODEL in settings.py.
- Update any forms or serializers to reference get_user_model() instead of importing User directly.
- Migrate carefully; swapping a user model mid‑project requires an empty database or custom migrations.
6. Permissions and Authorization
6.1 Model Permissions
Django auto‑generates add, change, delete, and view permissions for each model. You can assign these to users or groups in the admin.
6.2 Object‑level Permissions
Django’s default permissions are model‑level. For object‑level control, consider third‑party libraries like django-guardian.
6.3 Custom Permissions
Define custom permissions on your model:
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
class Meta:
permissions = [
('publish_article', 'Can publish articles'),
]Enforce them in views:
from django.contrib.auth.decorators import permission_required
@permission_required('blog.publish_article')
def publish(request, pk):
# Implementation7. Third‑Party Authentication
Integrating social logins—Google, Facebook, Twitter—enhances user experience.
7.1 OAuth via django-allauth
django-allauth simplifies social OAuth setups.
pip install django-allauth
Add to INSTALLED_APPS:
INSTALLED_APPS = [
# ...
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.google',
]
SITE_ID = 1Include its URLs:
path('accounts/', include('allauth.urls')),Configure provider credentials in the Django admin.
7.2 Social Authentication Flows
After configuration, users can log in via “Log in with Google,” and allauth handles the redirect dance, callback, and account linking.
8. Token‑Based Authentication for APIs
Web APIs often need stateless authentication.
8.1 Django REST Framework Tokens
DRF provides simple token auth:
pip install djangorestframework
Add to INSTALLED_APPS:
'rest_framework', 'rest_framework.authtoken',
Run migrations, then:
from rest_framework.authtoken.models import Token user = User.objects.first() token, created = Token.objects.get_or_create(user=user) print(token.key)
Configure DRF:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
}8.2 JSON Web Tokens (JWT)
For more scalable token management, use JWT with djangorestframework-simplejwt:
pip install djangorestframework-simplejwt
In settings.py:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}URLs:
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
urlpatterns += [
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]Clients request tokens and attach them in the Authorization: Bearer <token> header.
9. Multi‑Factor Authentication (MFA)
For heightened security, implement MFA. Popular packages include:
- django-otp: Provides one‑time password support (TOTP, SMS, email).
- django-two-factor-auth: Built on django-otp, offering device management and QR code provisioning.
Basic setup example with django-two-factor-auth:
pip install django-two-factor-auth qrcode[pil]
Add to INSTALLED_APPS:
'two_factor', 'otp_yubikey', # other otp providers...
Include URLs:
path('', include('two_factor.urls', 'two_factor')),Users set up their TOTP app (e.g., Authy, Google Authenticator) and must enter codes after passwords.
10. Best Practices and Security Considerations
10.1 Secure Password Storage
- Django uses PBKDF2 with a SHA256 hash by default. You can configure alternate password hashers in PASSWORD_HASHERS.
10.2 HTTPS and Secure Cookies
- Always serve authentication pages over HTTPS.
- Set SESSION_COOKIE_SECURE = True and CSRF_COOKIE_SECURE = True in production.
10.3 Limiting Login Attempts
To mitigate brute‑force attacks, use packages like django-axes:
pip install django-axes
Configure middleware:
MIDDLEWARE = [
'axes.middleware.AxesMiddleware',
# … other middleware …
]Axes locks out users/IPs after configured failed attempts.
11. Conclusion
Django’s authentication framework is powerful, flexible, and secure out of the box. From the default User model to fully customized authentication schemes, you can tailor the system to your application’s needs. By following best practices—using HTTPS, secure password storage, MFA, and cautious permission assignments—you’ll ensure that your users’ data and your site’s integrity remain protected. Dive into Django’s docs for more details, experiment with third‑party packages for extended functionality, and you’ll have a rock‑solid authentication layer in no time.