Prerequisites: Django, WebSockets, Django channels, Token authentication
The most popular Django topics right now are WebSockets and Django channels because they make it possible to communicate quickly and easily while working in real-time without constantly refreshing the page. When working with the Django templating engine alone and not the REST framework, the authentication method that Django channels employ is session authentication. The user who is currently logged in is also reflected in the Django channels auth system.
// This is not possible in websockets .
var socket = new WebSocket("path_of_the_socket" , headers = { "Authorization': "token token_string" })
Well, using web-based authentication is one way you could reach your goal. Returning a cookie to the website allows you to connect to the WebSocket server once more with the cookie in hand, authenticate, and then continue. However, cookie-based authentication can be extremely unreliable and have various problems. Therefore, to address this issue, we can convey the authentication token from the socket's query parameters and then build a new authentication stack that will sit on top of the existing ones when routing WebSocket connections.
However, working with the rest framework with token authentication or JWT authentication is not simple for WebSockets and channels; as a result, it can be challenging to log in to the user via channels and sockets when using token authentication or the rest framework. There is no way you can send auth/JWT tokens to the headers of a WebSocket like that of a simple post or get a request in the Authorization header.
Note: This process is totally asynchronous because WebSockets and channels work with ASGI (Asynchronous server gateway interface).
Setting up our Project
File Structure
This is the file structure after completing all the steps in this article.
Step 1: Create a virtual environment and activate it.
Step 2: Install Django and start your project.
Step 3: Create a project named TokenAuth
django-admin startproject TokenAuth
Step 4: Start an app named token_auth_app by moving to the project folder.
cd TokenAuth
python manage.py startapp token_auth_app
Step 5: Add your app to the installed apps in setting.py.
'token_auth_app.apps.TokenAuthAppConfig'
Step 6: To Set up Django channels for the backend part. Install Django-channels
python -m pip install -U channels
Step 7: Add channels to the installed apps.
Python
INSTALLED_APPS = [
'token_auth_app.apps.TokenAuthAppConfig',
'channels'
]
Step 8: Installing the REST framework is required to create token authentication for backend applications. For token authentication, the rest framework's auth token package, which contains a Token model, is used.
pip install django-rest-framework
Step 9: Install cors.
pip install django-cors-headers
Step 10: Add both to the INSTALLED_APPS and also token auth package.
Python
INSTALLED_APPS = [
'token_auth_app.apps.TokenAuthAppConfig',
...
'channels',
'rest_framework',
'rest_framework.authtoken',
'corsheaders',
]
Step 11: Set ALLOWED_HOSTS to *, Also, add the cors middleware to the MIDDLEWARE list The cors setup is done so that the host allows all the origins and we can communicate with the backend application.
Python
ALLOWED_HOSTS = ["*"]
CORS_ALLOW_ALL_ORIGINS = True
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
# -----------------------------------------
'corsheaders.middleware.CorsMiddleware',
# -----------------------------------------
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Token authentication is essential when working with WebSockets in Django Channels. If you want to explore such advanced Django features more thoroughly, the Complete Django Web Development Course - Basics to Advance offers detailed guidance
Code Implementation
Setting up files one by one:
token_auth_app/consumers.py file:
In the app folder create a consumers.py that will deal with all the incoming receive and send commands from the WebSocket
Python
from channels.generic.websocket import AsyncJsonWebsocketConsumer
class TokenAuthConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
await self.accept()
print(self.scope["user"].username)
print(self.scope["user"].email)
async def disconnect(self, close_code):
...
async def receive_json(self, message):
command = message.get("command")
if command == "Say hello !":
print(message["data_string"])
await self.send_json({
"command_response": "The command to \
say hello was received ",
"data_string_bacK": message.get
("data_string", None)
})
Code explanation:
We have created a Consumer with the class name TokenAuthConcumser as it consumes events sent and received by the ASGI application which we will see create later. Here, we inherit AsyncJsonWebsocketConsumer, which is the Parent Consumer class. In the AsyncJsonWebsocketConsumer module, we have send_json and receive_json functions which accept in JSON and send JSON without dumping JSON.
- connect function: The first and foremost function that is executed in order to establish a connection is the one that takes the WS to connect request, thus we must connect it. The scope is the dictionary, which functions similarly to the request parameter in function-based views (def fun(request)) in that it contains all the information about the incoming connection. user is accessed in scope as a dict object scope["user"], which will provide information on the user who is currently logged in. The user's username and email are then retrieved and displayed.
- disconnect function: Takes the close_code parameter and then does nothing.
- receive_json function: We must implement the receive method in AsyncWebsocketConsumer. then, in order to retrieve items, we must load the data (json.loads). However, you have direct access to the stuff here. This procedure uses the message sent from the front end. We will send this data as given below:
JavaScript
{
"command" : "Say hello !" ,
"data_string" : "This is the data string !" ,
}
As this data is received, we interpret it and send responses accordingly in the front end.
token_auth_app/middlewares.py file:
It will have the custom auth which we will create and the custom stack will be superposed above all the stacks.
Python
from rest_framework.authtoken.models import Token
from urllib.parse import parse_qs
from channels.db import database_sync_to_async
from django.contrib.auth.models import AnonymousUser
@database_sync_to_async
def returnUser(token_string):
try:
user = Token.objects.get
(key=token_string).user
except:
user = AnonymousUser()
return user
class TokenAuthMiddleWare:
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
query_string = scope["query_string"]
query_params = query_string.decode()
query_dict = parse_qs(query_params)
token = query_dict["token"][0]
user = await returnUser(token)
scope["user"] = user
return await self.app(scope, receive, send)
Code explanation:
The uses of different modules are described below:
- Token: This is used for token auth validation.
- parse_qs: It is used for parsing the query parameters from string to dict.
- database_sync_to_async: It is used for retrieving the data from the database as Django ORM is totally synchronous.
- AnonymousUser: This helps if we don't find the user based on the token, i.e. returnUser function returns the user related to the token passed to the function else it returns the AnonymousUser.
In the __init__ function we define the current instance app to the app which is passed into the stack. Next, the async __call__() function takes three parameters scope, receive and send. The scope is the dictionary which has all the data about the connection as stated above. send and receive are the commands for sending and receiving commands. Every ASGI application has three parameters environ, send and receive, here environ is the scope var. The query_string is the string passed from the front request, For example:
ws://localhost:8000/?token=fkdsahjkfshiadjkfhoasdfk"
The query string that is provided in the query string variable in scope is token=fkdsahjkfshiadjkfhoasdfk. It is sent in bytes as a string. This indicates that the query string's type is bytes.
The byte string is converted to a python string using a query string.decode(). p Parse qs(query params), on the other hand, decodes the string and adds it to the Python dictionary. The dict is presented as a key-value pair. Therefore, we access the token key, then access the token's first element, token=qury_dict["token"][0], and finally, we visit the returnUser method to obtain the user. and we set it to the scope's "user" property before returning the application.
The interesting part about this scope variable is that you can completely change it and make any changes you desire. This entails that you are free to change the variables in the scope parameter as well as add new ones.
for adding, just add like a normal Python dictionary, i.e. scope["some_another_key"] = "value_for_the_key",
for deleting, del scope["some_key_that_exist"]
TokenAuth/routing.py file:
It will create the ASGI application which will be served and which will route all the asynchronous WebSocket URLs to the respective consumers.
Python
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.urls import path
from token_auth_app.consumers import TokenAuthConsumer
from token_auth_app.middlewares import TokenAuthMiddleWare
application = ProtocolTypeRouter(
{
"websocket": TokenAuthMiddleWare(
AllowedHostsOriginValidator(
URLRouter(
[path("", TokenAuthConsumer.as_asgi())]
)
)
)
}
)
Code explanation:
The uses of different modules are described below:
- ProtocolTypeRouter: This routes the server of the whole application based on the type of protocol. If the protocol is HTTP it serves the Django WSGI app and if WS then the ASGI app.
- URLRouter: This routes the WS connection routes.
- AllowedHostsOriginValidator: This security stack is used to validate the connection and data acceptance only from the hosts which are allowed in the settings.py file of the Django application.
- path: Routing the path.
- TokenAuthConsumer: To serve the consumer instance for a particular connection.
- TokenAuthMiddleware: For setting user instance using token passed to the connection.
Then, set the stacks for serving the ASGI app in the application variable. Keep in mind that we make use of TokenAuthMiddleWare, and that's where we can set the user using the token. In the token auth app middlewares.py, we recently developed that class.
You may have noticed that we do not use AuthMiddlewareStack. This is because it is helpful when serving the ASGI app from the same application or templating engine. It stores the data in the sessions.
ASGI Application and Channel Layers in settings.py
Set your ASGI_APPLICATION will serve the required consumers and route. Whereas in CHANNEL_LAYERS, we are using InMemoryChannel this is for a development environment.
Python
WSGI_APPLICATION = 'TokenAuth.wsgi.application'
ASGI_APPLICATION = 'TokenAuth.routing.application'
CHANNEL_LAYERS = {
"default": {
"BACKEND":
"channels.layers.InMemoryChannelLayer",
}
}
token_auth_app/signals.py
This file creates a token object for each and every user that will be created and this signal.py will be imported by the apps.py file in the ready function.
Python
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from rest_framework.authtoken.models import Token
@receiver(post_save, sender=User)
def create_token(sender, instance, created, **kwargs):
if created:
token = Token.objects.create(user=instance)
token.save()
token_auth_app/apps.py
Now after setting all the application's backend, and database, this will add the token model, sessions, and rest framework into work.
Python
from django.apps import AppConfig
class TokenAuthAppConfig(AppConfig):
default_auto_field =
'django.db.models.BigAutoField'
name = 'token_auth_app'
def ready(self):
import token_auth_app.signals
token_auth_app/views.py
Here we will create a login page for the frontend part and from there we will make a post request with username and password then the backend view will validate whether the user is there or not, if the user is there then the token will be sent from the backend in the response and we will create a socket connection from there. For this, we will need a views.py which will have will handle login and send the token.
The uses of different modules are described below:
- Response: This is the response object which is sent from the API view
- api_view: It converts the normal Django view to the API view.
- authenticate: This will return the user, based on the username and password.
Python
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.authtoken.models import Token
from django.contrib.auth import authenticate
@api_view(["POST"])
def loginView(request, *args, **kwargs):
username = request.POST.get("username")
password = request.POST.get("password")
try:
user = authenticate(username=username,
password=password)
except:
user = None
if not user:
return Response({
"user_not_found": "There is no user \
with this username and password !"
})
token = Token.objects.get(user=user)
return Response({
"token": token.key,
})
TokenAuth/urls.py
We need to set the URL for this page in Project urls.py add this URL to the loginview with URL route = "api/login/". This file will handle the backend part for the login and will return a response on the basis of the username and the password.
Python
from django.contrib import admin
from django.urls import path
from token_auth_app.views import loginView
urlpatterns = [
path('admin/', admin.site.urls),
path("api/login/", loginView),
]
It will look like this:
testing_html.html file
After submitting a post request with a username and password, the file will be used to store the token that was received upon successful authentication. The TokenAuthMiddleWare in middlewares.py will assist us with this. Then, using Django channels, we will connect to a WebSocket to the backend and authenticate using the token.
HTML
<!DOCTYPE html>
<html>
<head>
<title>Token Auth</title>
</head>
<body>
<input type ="text" name = "username" id = "form_username" /><br>
<input type = "text" name = "password" id = "form_password" /><br>
<button onclick = "loginViaBackend()"> Login </button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
function createSocket(token) {
ws_path = "ws://localhost:8000/?token="+token ;
socket = new WebSocket(ws_path) ;
socket.onopen = function(e) {
console.log("Connected") ;
socket.send(
JSON.stringify(
{
"command" : "Say hello !" ,
"data_string" : "This is the data string !" ,
}
)
) ;
}
socket.onclose = function(e) {
console.log(e) ;
}
socket.onmessage = function(data) {
data = JSON.parse(data.data) ;
console.log(data) ;
console.log(data["command_response"])
}
}
function loginViaBackend() {
console.log("The function was run !") ;
var username = document.getElementById("form_username").value ;
var password = document.getElementById("form_password").value ;
console.log(username) ;
console.log(password) ;
payload = {
"username" : username ,
"password" : password ,
}
$.ajax(
{
"type": "POST" ,
"dataType" : "json" ,
"url" : "http://localhost:8000/api/login/" ,
"timeout" : 5000 ,
"data" : payload ,
"success" : function(data) {
console.log(data) ;
token = data["token"] ;
createSocket(token) ;
},
"error" : function(data) {
console.log(data) ;
}
}
) ;
}
</script>
</body>
</html>
Code explanation:
Once you click the login button the function loginViaBackend function is run and it makes a post request to the api/login URL which we have just created in the backend. (we are using ajax for making the post request), In the loginViaBackend function, we access the values of the username and the password and then send it via the post request. After the successful request we get the token from the backend as the successful request of a username and the password returns the token.
Create a superuser
python manage.py createsuperuser
I have created a superuser named, testuserone with password testing123, and suraj with password 123.
Migrate database
With the token, we run the function name createSocket(token), this takes and creates a WebSocket request to the backend server. Before running this part make sure to makemigrations and migrate the database.
python manage.py makemigrations
python manage.py migrate
Run the server in the localhost with port 8000 and create a socket connection with a token parameter in the query params of the request.
python manage.py runserver
path for WS connection,
ws_path = "ws://localhost:8000/?token="+token ;
The token is passed from the success parameter of the ajax post request. Then we create WS connection, once you get connected you will receive the data which was sent by the consumer.
Output:
First, we entered the correct login and password, which caused the token id to appear; second, we entered the incorrect password, which prevented the token from appearing.

To open the HTML file just copy the path of the file and paste it into your browser, or go to the folder and double-click on the file to launch the HTML file.
Similar Reads
Flask API Authentication with JSON Web Tokens
Authentication is the process of verifying the identity of the user. It checks whether the user is real or not. It is used to provide access to resources only to valid users. There are two types of Authentication: Single Factor Authentication: In this only one piece of information is needed to verif
7 min read
Django Channels - Introduction and Basic Setup
Django is a powerful Python framework for web development. It is fast, secure, and reliable. Channels allow Django projects to handle HTTP along with asynchronous protocols like WebSockets, MQTT, chatbots, and more. Channels: Channels preserve the synchronous behavior of Django and add a layer of as
6 min read
Basic Authentication - Django REST Framework
Authentication is a mechanism that provides access control based on the credentials associated with incoming requests. Django REST Framework provides several authentication schemes. In this section, let's look at the Basic Authentication in Django rest framework, i.e., authenticated against a user's
4 min read
How to authenticate a user in tests in Django
Testing user authentication in Django applications is a critical aspect of ensuring the security and functionality of our application. In Django, the testing framework provides a robust way to simulate user interactions, including authentication. This article will guide us through the process of aut
5 min read
Securing Django Admin login with OTP (2 Factor Authentication)
Multi factor authentication is one of the most basic principle when adding security for our applications. In this tutorial, we will be adding multi factor authentication using OTP Method. This article is in continuation of Blog CMS Project in Django. Check this out here â Building Blog CMS (Content
2 min read
User Authentication System using Django
In this article, we will explore the process of creating a secure and efficient user authentication system in Django, a high-level Python web framework. Building upon Django's built-in capabilities, we will cover user registration, login, and more, providing you with the knowledge and tools necessar
10 min read
JWT Authentication with Django REST Framework
JSON Web Token is an open standard for securely transferring data within parties using a JSON object. JWT is used for stateless authentication mechanisms for users and providers, this means maintaining session is on the client-side instead of storing sessions on the server. Here, we will implement t
2 min read
Implement Token Authentication using Django REST Framework
Token authentication refers to exchanging username and password for a token that will be used in all subsequent requests so to identify the user on the server side.This article revolves about implementing token authentication using Django REST Framework to make an API. The token authentication works
2 min read
Build an Authentication System Using Django, React and Tailwind
In this article, we will guide you in building an Authentication system using React and Tailwind with the Django Framework that includes features like sign up, log in, forgot password, and reset password. Weâll explore the integration of Django, React, and Tailwind CSS and go through the step-by-ste
15+ min read
Configuration for Django WebSocket Application on Ubuntu Server
This tutorial will walk you through each step in detail on how to configure your django websocket application on a Ubuntu 20.10 server. This article assumes you are familiar with Django and have a ubuntu remote server running up. To learn more about Django, checkout - Django Tutorial First, let's se
3 min read