Originally published at www.melvinkoh.me.
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
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.
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
Install djangorestframework_jwt with pip:
pip install djangorestframework_jwt
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.
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.
We will map our url to a built in view of djangorestframework_jwt. One for obtaining token, another for refreshing it.
# urls.pyfrom 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), ...]
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 -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"}
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/
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
Your clap will definitely drive me further. Give me a clap if you like this post.