Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to check token user for channels middeware? #258

Open
AlexCernik opened this issue Nov 11, 2021 · 1 comment
Open

How to check token user for channels middeware? #258

AlexCernik opened this issue Nov 11, 2021 · 1 comment

Comments

@AlexCernik
Copy link

Hi, I am using channels with drf and like connect only users authenticated to websocket, how to possible?. This my middleware code and asgy.py. Thanks.

from django.contrib.auth.models import AnonymousUser
from channels.db import database_sync_to_async
from channels.middleware import BaseMiddleware

@database_sync_to_async
def get_user(token_key):
    # check
    pass

class TokenAuthMiddleware(BaseMiddleware):
    def __init__(self, inner):
        super().__init__(inner)

    async def __call__(self, scope, receive, send):

        try:
            token_key = dict(scope['headers'])[b'sec-websocket-protocol'].decode('utf-8')
            print(token_key)
        except ValueError:
            token_key = None
        scope['user'] = AnonymousUser() if token_key is None else await get_user(token_key)
        return await super().__call__(scope, receive, send)
application = ProtocolTypeRouter({
    'http': django_asgi_app,
    'websocket': TokenAuthMiddleware(URLRouter(ws_urlspatterns))
})

I don't know how to speak much English, I speak Spanish, sorry.

@BisasterBoy32
Copy link

This is how I've implemented custom token authentication middleware

from django.utils.translation import gettext_lazy as _
from channels.auth import AuthMiddlewareStack
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import AnonymousUser
from knox.auth import TokenAuthentication
from asgiref.sync import sync_to_async


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

    async def __call__(self, scope, receive, send):
        headers = dict(scope['headers'])

        if b'cookie' in headers:
            cookie_header = str(headers[b'cookie'])
            if "X-Authorization=" in cookie_header:
                for slice in cookie_header.split(";"):
                    if " X-Authorization=" in slice:
                        token = slice.replace(" X-Authorization=", "").replace("'","")
                        token = token.encode()
                        try:
                            auth = TokenAuthentication()
                            token_obj = await sync_to_async(auth.authenticate_credentials)(token)
                            scope['user'] = token_obj[0]

                        except Exception as error:
                            print("Failed to get authenticate user: ", error)
                            scope['user'] = AnonymousUser()
                 
        return await self.inner(scope, receive, send)

TokenAuthMiddlewareStack = lambda inner: TokenAuthMiddleware(AuthMiddlewareStack(inner))

in the frontend just make sure to add the token as a cookie:

document.cookie = 'X-Authorization=' + token + '; path=/';

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants