Geek Culture
Published in

Geek Culture

djwto: Django Authentication with JWT

Introducing an alternative implementation for the auth layer using JWTs.

  • Works with either bearer tokens or cookies.
  • CSRF protected by default.
  • Offers decorators for protecting views (full authentication and authorization layers).
  • Fully customizable.

1. The Environment

We first need a Django project to begin with so let’s create one (for what follows it’s assumed a unix based system is used).Change directory to one that is empty and run the commands:

├── djwto_project
│ ├──
│ ├──
│ ├──
│ ├──
│ └──
  • DJWTO_MODE sets how the JWTs will be handled to the client. djwto works with two tokens: access and refresh. They are essentially the same thing but the former is short-lived and should be “refreshed” by using the latter, which in turn is long-lived. The mode of operation can be one of the following:
    - JSON: The JWTs are returned to the client as regular JSONs.
    - ONE-COOKIE: The JWTs are stored in cookies.
    - TWO-COOKIES: Similar to before but this time the access token is split into two parts. One is not encoded and therefore its payload is accessible by the client.
export DJWTO_SIGNING_KEY=’test key’ && python makemigrations
python migrate
python shell
python startapp testapp

2. Running djwto

To begin with, let’s use the requests library and send a login POST request with the user alice to see how it goes. First we need to run the server:

export DJWTO_SIGNING_KEY=’test key’ && python runsslserver

2.1 Login

Here’s the Python code to send a login request

refresh and access tokens returned in JSON mode.
#./djwto_project/settings.pyDJWTO_MODE = ‘TWO-COOKIES’
Cookie(name=’csrftoken’, value=’mzv…’), Cookie(name=’jwt_access_payload’, value=’eyJ…'), Cookie(name=’jwt_access_token’, value=’eyJ’, rest={‘HttpOnly’: None}), Cookie(name=’jwt_refresh’, value=’eyJ’, path=’/api/token/refresh’, rest={‘HttpOnly’: None})]>
Decoding the access JWT token.

2.2 Validate

Given that the tokens were created, at times it’s desired to check if they are still valid at some point. Suppose we are in JSON mode:

Valid response

3. Protecting Views

djwto offers direct protection of views by requiring the JWTs being available in the input request. For testing that, let’s create a view in our testapp like so:

# ./djwto_project/
from django.urls import path, include
urlpatterns = [
path('', include('djwto.urls')),
path('', include('testapp.urls'))
View is fully protected by the JWTs.

4. Customization

djwto was built aiming for being customizable. Let’s see an example. Using our testapp, let’s update the files to change how the users are processed when creating the tokens:

"aud": "aud",
"exp": 1624259339,
"iat": 1624229339,
"iss": "iss",
"jti": "900f4f1a-3e0f-4843-9997-9fd8d032684e",
"refresh_iat": 1624229339,
"sub": "sub",
"type": "access",
"user": {
"email": "",
"id": 1,
"perms": [],
"username": "alice"

5. Conclusion

This was djwto in a nutshell. Many other features are fully documented in the official repo:



A new tech publication by Start it up (

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Will Fuks

Mainly interested in data science and software development topics.