Authentication with JWT¶
JWT (JSON Web Token) is widely used for authentication but with that also brings certain level of concerns such as where to store the access and refresh tokens.
There are multiple ways:
- Local Storage - Prompt for XSS attacks.
- Session Storage - Deplects the UX of a user as it needs to login on each tab session.
- Cookie - Limited but with specific options and safer using
httpOnly = True.
Django Fast Utils covers the Cookies.
Cookie httpOnly¶
When a cookie is set to httpOnly true, JavaScript cannot read and/or access those values making the refresh and access tokens safer in the browser and reducing the attacks.
Installation¶
Django Fast Utils uses Django Rest Framework SimpleJWT
Settings¶
- Add
rest_framework_simplejwtandrest_framework_simple_jwt.token_blacklistto yoursettings.py
INSTALLED_APPS = [
...
'rest_framework_simplejwt',
'rest_framework_simplejwt.token_blacklist',
...
]
- Add the
django_fast_utils.auth.middleware.JWTRefreshRequestCookies' toMIDDLEWARE`.
MIDDLEWARE = [
...
'django_fast_utils.auth.middleware.JWTRefreshRequestCookies',
'django.contrib.auth.middleware.AuthenticationMiddleware',
...
]
- Update your
REST_FRAMEWORKsettings.
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
"DEFAULT_AUTHENTICATION_CLASSES": (
...
...
'django_fast_utils.auth.backends.JWTCustomAuthentication',
),
}
- Update the
SIMPLE_JWTto havedjango_fast_utilssettings for the authentication.
SIMPLE_JWT = {
...
# JWT FOR HTTP ONLY COOKIE SETTINGS
'AUTH_COOKIE': 'access', # Cookie name. Enables cookies if value is set.
'AUTH_COOKIE_DOMAIN': None, # A string like "example.com", or None for standard domain cookie.
'AUTH_COOKIE_SECURE': True, # Whether the auth cookies should be secure (https:// only).
'AUTH_COOKIE_HTTP_ONLY' : True, # Http only cookie flag. It's not fetch by JS.
'AUTH_COOKIE_PATH': '/', # The path of the auth cookie.
'AUTH_COOKIE_SAMESITE': 'Lax', # Whether to set the flag restricting cookie leaks on cross-site requests. This can be 'Lax', 'Strict', or None to disable the flag.
'REFRESH_COOKIE': 'refresh', # Cookie name. Enables cookies if value is set.
'REFRESH_COOKIE_DOMAIN': None, # A string like "example.com", or None for standard domain cookie.
'REFRESH_COOKIE_SECURE': True, # Whether the auth cookies should be secure (https:// only).
'REFRESH_COOKIE_HTTP_ONLY' : True, # Http only cookie flag.It's not fetch by JS.
'REFRESH_COOKIE_PATH': '/', # The path of the auth cookie.
'REFRESH_COOKIE_SAMESITE': 'Lax', # Flag restricting cookie leaks on cross-site requests. This can be 'Lax', 'Strict', or None to disable the flag.
}
- Add the
LoginJWTApiViewandLogoutJWTApiViewto your urls.
In your settings.py add DJANGO_FAST_UTILS setting:
DJANGO_FAST_UTILS = {
'LOGOUT_URL': ['/logout']
}
The LOGOUT_URL is expecting as list of possible logout urls used by the application.
This will ensure the middleware doesn't execute logic for specific views such as refresh of
tokens.
Default: ['/logout']
from django.urls import path
from django_fast_utils.views.auth.views import LoginJWTApiView, LogoutJWTApiView
urlpatterns = [
...
path('login', LoginJWTApiView.as_view(), name='login'),
path('logout', LoginJWTApiView.as_view(), name='logout')
...
]
That's it!. You can now login into your application using email and password and you
can see in your browser that the cookies are now set as httpOnly true.
Refresh¶
Djago Fast Utils middleware handles with the automatic refresh of the token based on the
settings you added on the default SIMPLE_JWT settings.
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=200),
...
}