How to check token user for channels middeware?
AlexCernik opened this issue · 1 comments
AlexCernik commented
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 commented
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=/';