Skip to content

Django Channels WebSocket Auth Fix

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about Django Channels WebSocket Auth Fix. We cover key concepts, practical examples, and best practices.

The Problem

WebSocket connections don't use HTTP sessions or cookies the same way. Without proper auth middleware, self.scope['user'] is an anonymous user, even if the client sent a valid session cookie.

Quick Fix

Wrong — direct consumer without auth

class ProtectedConsumer(WebsocketConsumer):
    def connect(self):
        # self.scope['user'] is AnonymousUser
        self.accept()

Output: Anyone can connect. No user identification. self.scope['user'].is_authenticated is always False.

Correct — AuthMiddlewareStack

# asgi.py
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from myapp.routing import websocket_urlpatterns

application = ProtocolTypeRouter({
    'websocket': AuthMiddlewareStack(
        URLRouter(websocket_urlpatterns)
    ),
})

Output: self.scope['user'] is populated from the session cookie. Authenticated users are identified.

Rejecting unauthenticated connections

class ProtectedConsumer(WebsocketConsumer):
    def connect(self):
        if not self.scope['user'].is_authenticated:
            self.close()
        else:
            self.accept()

    def receive(self, text_data):
        print(f"User {self.scope['user']} sent: {text_data}")

Token-based WebSocket auth

from channels.db import database_sync_to_async
from channels.middleware import BaseMiddleware
from rest_framework.authtoken.models import Token

class TokenAuthMiddleware(BaseMiddleware):
    async def __call__(self, scope, receive, send):
        query = dict(parse_qs(scope['query_string']))
        token_key = query.get('token', [None])[0]
        if token_key:
            try:
                scope['user'] = await database_sync_to_async(
                    Token.objects.get(key=token_key).user
                )
            except Token.DoesNotExist:
                pass
        return await super().__call__(scope, receive, send)

Client-side token auth

// Browser WebSocket with token
const ws = new WebSocket(`ws://example.com/ws/chat/?token=${encodeURIComponent(token)}`);

Prevention

  • Always wrap WebSocket routers with AuthMiddlewareStack.
  • Check self.scope['user'].is_authenticated in connect().
  • Use token-based auth for non-session clients (mobile apps).

Common Mistakes with channels websocket auth

  1. Forgetting deriving (Show, Eq) on custom data types needed for debugging
  2. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  3. Using head and tail instead of pattern matching, causing runtime errors on empty lists

These mistakes appear frequently in real-world DJANGO code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### Does AuthMiddlewareStack work with Django sessions?

Yes. It reads the session cookie from the HTTP handshake and populates scope['user'].

Can I use JWT with Channels?

Yes. Pass the token as a query parameter and extract it in custom middleware as shown above.

Is the user available in async consumers?

Yes. self.scope['user'] is populated by the middleware before the consumer handler runs.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro