Django: Middleware for JWT Token Encryption and Cookie Setting
I'm working on implementing JWT token encryption in my Django application using rest_framework_simplejwt
. I've created a custom middleware TokenEncryptionMiddleware
that encrypts access and refresh tokens before setting them as cookies. However, the client-side seems to receive the unencrypted response from TokenObtainPairView
.
What am I missing here? Are there any interactions between rest_framework_simplejwt
and custom middleware that I need to be aware of to ensure my encryption works as intended?
Here's my middleware code:
"""
Middleware for crypting the JWT tokens before setting them as cookies.
"""
from base64 import urlsafe_b64encode
from cryptography.fernet import Fernet
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
class TokenEncryptionMiddleware(MiddlewareMixin):
"""
Middleware to encrypt the JWT tokens before setting them as cookies.
"""
def process_response(self, request, response):
"""
Encrypts the JWT tokens before setting them as cookies.
"""
if response.status_code == 200 and (
"access" in response.data and "refresh" in response.data
):
base_key = settings.JWT_KEY.encode()[:32]
cipher = Fernet(urlsafe_b64encode(base_key))
encrypted_access_token = cipher.encrypt(
response.data["access"].encode()
).decode()
encrypted_refresh_token = cipher.encrypt(
response.data["refresh"].encode()
).decode()
del response.data["access"]
del response.data["refresh"]
response.set_cookie(
"access_token",
encrypted_access_token,
httponly=True,
secure=True,
samesite="Strict",
)
response.set_cookie(
"refresh_token",
encrypted_refresh_token,
httponly=True,
secure=True,
samesite="Strict",
)
return response
Middleware order
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"middlewares.crypter.TokenEncryptionMiddleware",
]
Expected behavior:
The client should receive cookies named access_token and refresh_token containing the encrypted JWT tokens.
There is a magic method required to create custom middleware in the form of a class.
class TokenEncryptionMiddleware(MiddlewareMixin):
"""
Middleware to encrypt the JWT tokens before setting them as cookies.
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
self.process_response(request, response)
return response
def process_response(self, request, response):
"""
Encrypts the JWT tokens before setting them as cookies.
"""
...
In Django Middleware, the __call__magic
method is called upon request, response.
Your jwt
token encryption process is expected to run in the response, so I added it in the __call__magic
method.