JWT Authentication in Vue.js and Django Rest Framework - Part 1

Previously I have posted about using API key or token authentication in DRF, on how we could generate a 40-character token using DRF authtoken module. You can refer it in this post

In this post, I will be setting up JWT Authentication in DRF and Vue.js in 2 parts. The first part will be setting up the DRF backend, you can refer to Part 2 at here

What is JWT?

JWT stands for JSON Web Token. JWT is a short-lived token issued by server for clients to authenticate themselves without having to maintain an active session.

Why use JWT?

JWT versus API key

API key is usually generated and that's it! It usually doesn't expire unless such mechanism is implemented on server side. By using API key, each request to server will include a header with the key. API key creates security issue if such key are exposed to unauthorized user (i.e: captured in man-in-the-middle attack). It could be used by unauthorized party to perform legit request.

Unlike API token, JWT has an expiry timestamp, it has to be constantly renewed or refreshed to keep the token valid.
If such token is exposed to third party, he/she might not be able to refresh the token and it will be invalidated after it's expiring timestamp.

To keep track of all user sessions, server has to maintain a record of those. In Django, user sessions are stored and maintained in it's underlying DB. This constraints scalability of the system, even if system are distributed and scaled horizontally, each node will still have to retrieve the session data stored in underlying database. Second, it is even more complex to make your session universal across multiple domains.

JWT can save you a lot of fuss when dealing with authentication across multiple domain and horizontal scalability since there is no need to keep session stored. To learn how exactly JWT works, refer to the JWT Introduction

This is a great article to get your familiarized with JWT mechanism in a few minutes. Link

Set up Django Rest Framework Backend

Install djangorestframework_jwt

Install djangorestframework_jwt with pip:

pip install djangorestframework_jwt

Add JSONWebTokenAuthentication

You can add the JSONWebTokenAuthentication mechanism either by including it a default authentication class in your settings.py or in your authentication_class of your DRF generic views (APIView, ListAPIView, CreateAPIView, etc)

In this case, I prefer the latter.

# views.py
... relevant imports ...

class PostsView(ListAPIView):
  authentication_class = (JSONWebTokenAuthentication,) # Don't forget to add a 'comma' after first element to make it a tuple
  permission_classes = (IsAuthenticated,)

  ...

Now your View above is guarded by IsAuthenticated and all request has to be authenticated with a JWT.

Configuring Your JWT Authentication

We will configure our JWT Authentication backend to set the validity of each token to 1 hour with a maximum lifespan of 7 days. It means that each token will expire in 1 hour after issuance, and you can only refresh it to the maximum lifespan up to 7 days. You will not be able to refresh the token if your token lifespan is depleted.

Add the following into your settings.py:

# settings.py

JWT_AUTH = {
    'JWT_ALLOW_REFRESH': True,
    'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=1),
    'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
}

Refer to official documentation to learn more about available settings.

Obtain and Refresh JWT Endpoints

We will map our url to a built in view of djangorestframework_jwt. One for obtaining token, another for refreshing it.

# urls.py
from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token

urlpatterns = [
  ...
  url(r'^auth/obtain_token/', obtain_jwt_token),
  url(r'^auth/refresh_token/', refresh_jwt_token),
  ...
]

Test Your Endpoints

Before using it, make sure your have your User created in your DB. You can test your endpoints using Postman or curl by posting a request with the following JSON payload:

  {
    "username": "<your_username>",
    "password": "<your_password>"
  }

Curl command

$ curl -X POST -H "Content-Type: application/json" -d '{"username":"<your_username>","password":"<your_password>"}' http://<your_domain_and_port>/auth/obtain_token

You will get a similar response:

{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Im1lbHZpbiIsImV4cCI6MTUxMjgyNzc1NSwiZW1haWwiOiJtZWx2aW5rY3hAaG90bWFpbC5jb20iLCJvcmlnX2lhdCI6MTUxMjc0MTM1NX0.xiPc-3xM9LcfsmuufvhwpjbqwZIHKTlrwwbo9pnLauU"
}

Refresh Token

To refresh your token, simply POST your existing token to the refresh_jwt_token endpoint, and you will expect a new token.

$ curl -X POST -H "Content-Type: application/json" -d '{"token":"<EXISTING_TOKEN>"}' http://<your_domain_and_port>/auth/refresh_token/

Consume Your REST Service from Vue.js

Your DRF back-end is now ready to accept incoming requests with JWT Authentication enabled. We will look at how to consume these services from Vue.js in Part 2

First published on 2017-12-08

Republished on Hackernoon

No Comments Yet