Web TippsUse custom web fonts in Google Sheets charts(08.09.2026 um 17:05 Uhr)
Web TippsIntroducing the new 1Password App for Google Chat(08.09.2026 um 18:02 Uhr)
Web TippsUse custom web fonts in Google Sheets charts(08.09.2026 um 17:05 Uhr)
Web TippsIntroducing the new 1Password App for Google Chat(08.09.2026 um 18:02 Uhr)

🔧 Programmierung 🕛 vor 5 Monaten 7 Min Lesezeit
0

Go beyond Django's built-in auth — learn JWT, custom email login, role-based permissions, and brute-force protection.

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Django Authentication Deep Dive: JWT, Sessions, and Custom Backends



Go beyond Django's built-in auth — learn JWT, custom email login, role-based permissions, and brute-force protection. Intermediate | Read Time: 12 min | Author: [SRI BALU]









Introduction



Authentication is the backbone of almost every web application. Django ships with a solid built-in auth system — but in real-world projects, you'll quickly outgrow it. Whether you're building a REST API, a multi-tenant SaaS, or a social login platform, understanding Django's authentication internals gives you the power to customize it exactly how you need.



In this deep-dive, we'll cover:




  • How Django's authentication system works under the hood

  • Session-based vs JWT-based authentication

  • Implementing JWT authentication with djangorestframework-simplejwt

  • Writing a custom authentication backend (e.g., login with email instead of username)

  • Securing your endpoints with permissions









1. How Django Authentication Works Under the Hood



Before writing any code, it helps to understand what happens when a user logs in.



Django's auth system revolves around three core components:
























Component Role

User model
Stores credentials (username, password hash)
AuthenticationBackend Validates credentials

Session / Token
Maintains state after login


When you call authenticate(request, username=..., password=...), Django loops through all backends listed in AUTHENTICATION_BACKENDS and returns the first User object that matches — or None.




CODE
# django/contrib/auth/__init__.py (simplified)
def authenticate(request=None, **credentials):
for backend_path in settings.AUTHENTICATION_BACKENDS:
backend = load_backend(backend_path)
try:
user = backend.authenticate(request, **credentials)
except PermissionDenied:
return None
if user is None:
continue
user.backend = backend_path
return user
return None






The default backend is django.contrib.auth.backends.ModelBackend, which checks the database for a matching username + password hash.









2. Session-Based Authentication (The Django Default)



Django's default auth uses server-side sessions. Here's the flow:




CODE
User submits login form
→ Django validates credentials
→ Creates a session in the DB (django_session table)
→ Sends a session cookie (sessionid) to the browser
→ On every request, browser sends the cookie
→ Django looks up the session → finds the user









Setting it up (already built-in):






CODE
# settings.py
INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.sessions',
...
]

MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
...
]









Login/Logout views:






CODE
# views.py
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import redirect, render

def login_view(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('dashboard')
else:
return render(request, 'login.html', {'error': 'Invalid credentials'})
return render(request, 'login.html')

def logout_view(request):
logout(request)
return redirect('login')









When to use sessions:




  • Traditional Django web apps (not APIs)

  • Server-rendered templates

  • When you control both frontend and backend









3. JWT Authentication for REST APIs



For Django REST Framework (DRF) APIs — especially those consumed by React, Flutter, or mobile apps — JWT (JSON Web Tokens) is the preferred approach.






Why JWT over sessions for APIs?

































Sessions JWT
State Server-side Stateless
Scalability Requires shared DB Works across servers
Mobile support Cookie issues Easy via headers
Logout Simple Requires token blacklist





Installation:






CODE
pip install djangorestframework djangorestframework-simplejwt









CODE
# settings.py
INSTALLED_APPS = [
...
'rest_framework',
]

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
}

from datetime import timedelta

SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'ALGORITHM': 'HS256',
'AUTH_HEADER_TYPES': ('Bearer',),
}









URL configuration:






CODE
# urls.py
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenBlacklistView,
)

urlpatterns = [
path('api/auth/login/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('api/auth/logout/', TokenBlacklistView.as_view(), name='token_blacklist'),
]









Protecting API views:






CODE
# views.py
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def profile_view(request):
user = request.user
return Response({
'id': user.id,
'username': user.username,
'email': user.email,
})









How to call the API:






CODE
# Step 1: Get tokens
curl -X POST http://localhost:8000/api/auth/login/ \
-H "Content-Type: application/json" \
-d '{"username": "john", "password": "secret123"}'

# Response:
# {"access": "eyJ0eXAiOiJKV...", "refresh": "eyJ0eXAiOiJKV..."}

# Step 2: Call protected endpoint
curl -X GET http://localhost:8000/api/profile/ \
-H "Authorization: Bearer eyJ0eXAiOiJKV..."












4. Custom Authentication Backend: Login with Email



By default, Django uses username to authenticate. In modern apps, users expect to log in with their email address. Here's how to write a custom backend:




CODE
# backends.py
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model

User = get_user_model()

class EmailBackend(ModelBackend):
"""
Authenticate using email instead of username.
Falls back to username if email not found.
"""
def authenticate(self, request, username=None, password=None, **kwargs):
try:
# Try to find user by email
user = User.objects.get(email=username)
except User.DoesNotExist:
# Fall back to username lookup
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
return None

if user.check_password(password) and self.user_can_authenticate(user):
return user
return None









Register the backend:






CODE
# settings.py
AUTHENTICATION_BACKENDS = [
'myapp.backends.EmailBackend',
'django.contrib.auth.backends.ModelBackend', # keep as fallback
]






Now authenticate(request, username="[email protected]", password="secret") will work automatically — no other code changes needed!









5. Custom JWT Payload (Add Extra Claims)



By default, JWT tokens contain only user_id. You can add extra data like role, email, or is_staff:




CODE
# serializers.py
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer

class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)

# Add custom claims
token['email'] = user.email
token['username'] = user.username
token['is_staff'] = user.is_staff
token['role'] = getattr(user, 'role', 'user') # if you have a role field

return token

# views.py
from rest_framework_simplejwt.views import TokenObtainPairView

class CustomTokenObtainPairView(TokenObtainPairView):
serializer_class = CustomTokenObtainPairSerializer









CODE
# urls.py
path('api/auth/login/', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'),












6. Role-Based Permissions



Once authentication is set up, you'll want authorization — controlling what users can do.






Built-in permission classes:






CODE
from rest_framework.permissions import (
IsAuthenticated, # Must be logged in
IsAdminUser, # Must be staff/superuser
IsAuthenticatedOrReadOnly, # Read for all, write for authenticated
)









Custom permission class:






CODE
# permissions.py
from rest_framework.permissions import BasePermission

class IsOwnerOrAdmin(BasePermission):
"""
Allow access only to object owners or admin users.
"""
def has_object_permission(self, request, view, obj):
if request.user.is_staff:
return True
return obj.owner == request.user


# views.py
from rest_framework import generics
from .permissions import IsOwnerOrAdmin
from .models import Post
from .serializers import PostSerializer

class PostDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [IsAuthenticated, IsOwnerOrAdmin]












7. Security Best Practices






✅ Always do this:






CODE
# settings.py

# Use HTTPS in production
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

# Prevent XSS from stealing session cookies
SESSION_COOKIE_HTTPONLY = True

# Limit session age
SESSION_COOKIE_AGE = 1209600 # 2 weeks in seconds

# Password validation
AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {'min_length': 8}},
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
]









✅ Rate-limit login attempts:






CODE
pip install django-axes









CODE
# settings.py
INSTALLED_APPS = ['axes', ...]
AUTHENTICATION_BACKENDS = [
'axes.backends.AxesStandaloneBackend',
'myapp.backends.EmailBackend',
]
AXES_FAILURE_LIMIT = 5 # Lock after 5 failed attempts
AXES_COOLOFF_TIME = 1 # Unlock after 1 hour












Summary



Here's what we covered:




































Topic Use Case
Session auth Traditional Django web apps
JWT with simplejwt REST APIs, mobile apps
Custom EmailBackend Login with email
Custom JWT claims Pass role/email in token
Custom permissions Role-based access control
django-axes Brute-force protection


Django's auth system is designed to be extended — not replaced. By understanding how backends, sessions, and tokens work together, you can build secure, scalable authentication for any use case.









What's Next?





  • Part 2: OAuth2 & Social Login with django-allauth (Google, GitHub)


  • Part 3: Two-Factor Authentication (2FA) with TOTP


  • Part 4: Multi-tenant authentication with row-level security






Found this helpful? Share it on Twitter and tag me! Have questions? Drop them in the comments below.






Tags: django python authentication jwt django-rest-framework web-development backend

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
3 Quellen
Use custom web fonts in Google Sheets charts
2 Quellen
Introducing the new 1Password App for Google Chat
1 Quelle
Context-aware access controls are available for Gemini Enterprise in the Admin console
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Go beyond Django's built-in auth — learn JWT, custom email login, role-based permissions, and brute-force protection.

Thematisch verwandte Begriffe: beyond, Djangos, builtin, auth · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...