question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Database query in custom authentication cause SynchronousOnlyOperation Error

See original GitHub issue

In Custom Authentication section of documentation, there is database query in __call__ method:

def __call__(self, scope):
        ...
        user = User.objects.get(id=int(scope["query_string"]))
        ...

It’s OK with Django 2, but in Django 3 it cause django.core.exceptions.SynchronousOnlyOperation error. please update docs, and explain how to use database query in Custom Authentications. Thanks.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:25
  • Comments:18 (8 by maintainers)

github_iconTop GitHub Comments

35reactions
AmirMahmoodcommented, Mar 12, 2020

@jkupka You can use below code, Until docs be updated.

from channels.db import database_sync_to_async

@database_sync_to_async
def get_user(user_id):
    try:
        return User.objects.get(id=user_id)
    except User.DoesNotExist:
        return AnonymousUser()

class QueryAuthMiddleware:
    """
    Custom middleware (insecure) that takes user IDs from the query string.
    """

    def __init__(self, inner):
        # Store the ASGI application we were passed
        self.inner = inner

    def __call__(self, scope):
        return QueryAuthMiddlewareInstance(scope, self)


class QueryAuthMiddlewareInstance:
    def __init__(self, scope, middleware):
        self.middleware = middleware
        self.scope = dict(scope)
        self.inner = self.middleware.inner

    async def __call__(self, receive, send):
        self.scope['user'] = await get_user(int(self.scope["query_string"]))
        inner = self.inner(self.scope)
        return await inner(receive, send)

TokenAuthMiddlewareStack = lambda inner: TokenAuthMiddleware(AuthMiddlewareStack(inner))
12reactions
daxaxelrodcommented, May 4, 2020

Hey, thanks for the work done thus far! Adapted @AmirMahmood solution for django rest framework’s token auth based on the old impl. See below:

@database_sync_to_async
def get_user(token_key):
    try:
        return get_user_model().objects.get(auth_token__key=token_key)
    except get_user_model().DoesNotExist:
        return AnonymousUser()

class TokenAuthMiddlewareInstance:
    """
    Token authorization middleware for Django Channels 3
    """

    def __init__(self, scope, middleware):
        self.middleware = middleware
        self.scope = dict(scope)
        self.inner = self.middleware.inner

    async def __call__(self, receive, send):
        headers = dict(self.scope['headers'])
        if b'authorization' in headers:
            token_name, token_key = headers[b'authorization'].decode().split()
            if token_name == 'Token':
                self.scope['user'] = await get_user(token_key)
        inner = self.inner(self.scope)
        return await inner(receive, send)

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

    def __call__(self, scope):
        return TokenAuthMiddlewareInstance(scope, self)


TokenAuthMiddlewareStack = lambda inner: TokenAuthMiddleware(AuthMiddlewareStack(inner))
Read more comments on GitHub >

github_iconTop Results From Across the Web

python 3.x - Rarely get SynchronousOnlyOperation error in ...
What happens if you access your resource by going directly to the DB, without using the ORM? Django ORM is not allowing async...
Read more >
[Solved]-SynchronousOnlyOperation Error in with django 3 ...
I have opened an issue for django channels about updating docs. @database_sync_to_async def get_user(token_key): try: return Token.objects.get(key=token_key).
Read more >
Django Exceptions
SuspiciousMultipartForm; SuspiciousSession; TooManyFieldsSent. If a SuspiciousOperation exception reaches the ASGI/WSGI handler level it is logged at the Error ...
Read more >
Custom Query – Django - djello
Support dictionaries in Field.choices for named groups. assigned, Tom Forbes, New feature, Database layer (models, ORM), dev. #31304 · PostgreSQL full-text ...
Read more >
Compare Django release notes | CodeReview.doctor
Fixed a bug in Django 3.2 that caused a migration crash on MySQL 8.0.13+ when altering ... As a side-effect the private API...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found