djangoflutterwebsocketjwtdjango-channels

Websocket jwt authentification keeps handshaking and disconnecting


I have this custom jwt auth-middleware in django:

class JWTAuthMiddleware:
def __init__(self, inner):
    self.inner = inner

async def __call__(self, scope, receive, send):
    print(": Middleware called")  
    headers = dict(scope['headers'])
    if b'authorization' in headers:
        print(": Authorization header found") 
        try:
            token_name, token_key = headers[b'authorization'].split()
            if token_name == b'Bearer':
                print(": Bearer token found")  
                user = await self.authenticate(token_key.decode())
                if user is not None:
                    print(": User authenticated")
                    scope['user'] = user
        except InvalidTokenError:
            print(": Invalid token")  
            await self.inner(dict(scope, user=None), receive, send)
            return
        except KeyError:
            print(": Invalid token format") 
            await self.send_error(send, "Invalid token format")
            return
    else:
        print(": No authorization header found") 
        await self.inner(dict(scope, user=None), receive, send)

async def authenticate(self, token_key):
    print(": Authenticating user") 
    try:
        secret_key = settings.SECRET_KEY
        decoded_token = decode(token_key, secret_key, algorithms=['HS256'])
        user_id = decoded_token['user_id']
        user = await self.get_user(user_id)
        if user is not None and user.is_authenticated:
            print(": User authenticated successfully")
            return user
    except (InvalidTokenError, KeyError):
        print(": Authentication failed")  
        pass
    return None

@database_sync_to_async
def get_user(self, user_id):
    print(": Retrieving user from database") 
    try:

        return User.objects.get(user_id=user_id)
    except User.DoesNotExist:
        print(": User not found")  
        return None

When i make a request through postman or flutter,after a user logs in and selects a group to access its chat_screen :

void _initializeWebSocket() async {
print("_initializeWebSocket called");
SharedPreferences prefs = await SharedPreferences.getInstance();
String? accessToken = prefs.getString('accessToken');

if (accessToken != null) {
  print("Initializing WebSocket channel");
  channel = IOWebSocketChannel.connect(
    'ws://192.168.1.3:8000/ws/chat/${widget.groupId}/',
    headers: {
      'Authorization': 'Bearer $accessToken',
    },
  );
  print("WebSocket channel initialized successfully");
} else {
  print("Access token not found");
  throw Exception('Access token not found');
}

} i get this in my django terminal:

    WebSocket HANDSHAKING /ws/chat/3/ [192.168.1.2:35476]
: Middleware called
: Authorization header found
: Bearer token found
: Authenticating user
: Retrieving user from database
: User authenticated successfully
: User authenticated
WebSocket DISCONNECT /ws/chat/3/ [192.168.1.2:35476]

and in flutter i get :

Initializing WebSocket channel

I/flutter (26511): WebSocket channel initialized successfully

E/flutter (26511): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: HttpException: Connection reset by peer, uri = http://192.168.1.3:8000/ws/chat/

this is my connect method in consumers.py:

async def connect(self):
        self.group_id = self.scope['url_route']['kwargs']['group_id']
        self.user = self.scope.get('user')
        if self.user is None:
            print("what")
            await self.close()
            return
        //removed save_user_channel to see if its the problem but it wasn't
        await self.accept()

Can you help me find the reason the websocket keeps disconnecting after handshake.


Solution

  • It seems the __call__ method of the Middleware is not running the inner application along with the scope. Try to return this after user authenticated successfully:

    return await self.inner(scope, receive, send)