jwt diagram

JWT Authentication in Django

This tutorial will give an introduction to JSON Web Tokens (JWT) and how to implement JWT authentication in Django.

What Is JWT?

JWT is an encoded JSON string that is passed in headers to authenticate requests. It is usually obtained by hashing JSON data with a secret key. This means that the server doesn’t need to query the database every time to retrieve the user associated with a given token.

How JSON Web Tokens Work

When a user successfully logs in using their credentials, a JSON Web Token is obtained and saved in local storage. Whenever the user wants to access a protected URL, the token is sent in the header of the request. The server then checks for a valid JWT in the Authorization header, and if found, the user will be allowed access.

A typical content header will look like this:

Authorization:
Bearer eyJhbGciOiJIUzI1NiIsI

Below is a diagram showing this process:

How JSON Web Tokens Work

The Concept of Authentication and Authorization

Authentication is the process of identifying a logged-in user, while authorization is the process of identifying if a certain user has the right to access a web resource.

API Example

In this tutorial, we are going to build a simple user authentication system in Django using JWT as the authentication mechanism.

Requirements

  • Django
  • Python

Let’s get started.

Create a directory where you will keep your project and also a virtual environment to install the project dependencies.

Activate the virtual environment:

Create a Django project.

Install DRF and django-rest-framework-jwt using pip.

Let’s go ahead and add DRF to the list of installed apps in the settings.py file.

Configure the JWT Settings

In order to use JWT, we need to configure django-rest-framework permissions to accept JSON Web Tokens.

In the settings.py file, add the following configurations:

Create a new app called users which will handle user authentication and management.

Add the users application to the list of installed apps in the settings.py file.

Setting Up the Database

We are going to use the PostgreSQL database because it’s more stable and robust.

Create the auth database and assign a user.

Switch over to the Postgres account on your machine by typing:

Access the Postgres prompt and create the database:

Create a role:

Grant database access to the user:

Install the psycopg2 package, which will allow us to use the database we configured:

Edit the currently configured SQLite database and use the Postgres database.

Creating Models

Django comes with a built-in authentication system which is very elaborate, but sometimes we need to make adjustments, and thus we need to create a custom user authentication system. Our user model will be inheriting from the AbstractBaseUser class provided by django.contrib.auth.models.

In users/models.py, we start by creating the User model to store the user details.

REQUIRED_FIELDS contains all required fields on your user model, except the username field and password, as these fields will always be prompted for.

UserManager is the class that defines the create_user and createsuperuser methods. This class should come before the AbstractBaseUser class we defined above. Let’s go ahead and define it.

Migrations

Migrations provide a way of updating your database schema every time your models change, without losing data.

Create an initial migration for our users model, and sync the database for the first time.

Creating a Superuser

Create a superuser by running the following command:

Creating New Users

Let’s create an endpoint to enable registration of new users. We will start by serializing the User model fields. Serializers provide a way of changing data to a form that is easier to understand, like JSON or XML. Deserialization does the opposite, which is converting data to a form that can be saved to the database.

Create users/serializers.py and add the following code.

CreateUserAPIView

Next, we want to create a view so the client will have a URL for creating new users.

In users.views.py, add the following:

We set permission_classes to (AllowAny,) to allow any user (authenticated or not) to access this URL.

Configuring URLs

Create a file users/urls.py and add the URL to match the view we created. Also add the following code.

We also need to import URLs from the users application to the main django_auth/urls.py file. So go ahead and do that. We are using the include function here, so don’t forget to import it.

Now that we are done creating the endpoint, let’s do a test and see if we are on track. We will use Postman to do the tests. If you are not familiar with Postman, it’s a tool which presents a friendly GUI for constructing requests and reading responses.

Configuring URLs

As you can see above, the endpoint is working as expected.

Authenticating Users

We will make use of the Django-REST Framework JWT Python module we installed at the beginning of this tutorial. It adds JWT authentication support for Django Rest Framework apps.

But first, let’s define some configuration parameters for our tokens and how they are generated in the settings.py file.

  • JWT_VERIFY: It will raise a jwt.DecodeError if the secret is wrong.
  • JWT_VERIFY_EXPIRATION: Sets the expiration to True, meaning Tokens will expire after a period of time. The default time is five minutes.
  • JWT_AUTH_HEADER_PREFIX: The Authorization header value prefix that is required to be sent together with the token. We have set it as Bearer, and the default is JWT.

In users/views.py, add the following code.

In the code above, the login view takes username and password as input, and it then creates a token with the user information corresponding to the passed credentials as payload and returns it to the browser. Other user details such as name are also returned to the browser together with the token. This token will be used to authenticate in future requests.

The permission classes are set to allowAny since anyone can access this endpoint.

We also store the last login time of the user with this code.

Every time the user wants to make an API request, they have to send the token in Auth Headers in order to authenticate the request.

Let’s test this endpoint with Postman. Open Postman and use the request to authenticate with one of the users you created previously. If the login attempt is successful, the response will look like this:

A sample response

Retrieving and Updating Users

So far, users can register and authenticate themselves. However, they also need a way to retrieve and update their information. Let’s implement this.

In users.views.py, add the following code.

We first define the permission classes and set to IsAuthenticated since this is a protected URL and only authenticated users can access it. 

We then define a get method to retrieve user details. After retrieving user details, an authenticated user will then update their details as desired.

Update your URLs to define the endpoint as follows.

In order for the request to be successful, the headers should contain the JWT token as shown below.

Headers with the JWT Token

If you attempt to request a resource without the authentication header, you will get the following error.

An example error

If a user stays beyond the time specified in JWT_EXPIRATION_DELTA without making a request, the token will expire and they will have to request another token. This is also demonstrated below.

JWT_EXPIRATION_DELTA Example

Conclusion

This tutorial has covered what is necessary to successfully build a solid back-end authentication system with JSON Web Tokens.

Powered by WPeMatico

Leave a Comment

Scroll to Top