jazzband / django-oauth-toolkit

OAuth2 goodies for the Djangonauts!
https://django-oauth-toolkit.readthedocs.io
Other
3.12k stars 792 forks source link

AccessToken matching query does not exist | Grant Type Password #995

Open ZuSe opened 3 years ago

ZuSe commented 3 years ago

Describe the bug Token Creation with grant_type password leads sometimes to "AccessToken matching query does not exist." error

To Reproduce

  1. Setup a Django Project with ASGI, running multiple workers (e.g. with uvicorn/daphne)
  2. Try multiple requests against /oidc/token/ (default /o/token/
  3. At some point it will throw the exception

Expected behavior No exception should be thrown, every client should return the token back.

Version OAuth-Toolkit: 1.5.0 Django: 3.2.5 Uvicorn: 0.14.0 Gunicorn: 20.1.0

Additional context Here is the call stack from sentry.:

AccessToken.DoesNotExist: AccessToken matching query does not exist.
  File "asgiref/sync.py", line 482, in thread_handler
    raise exc_info[1]
  File "django/core/handlers/exception.py", line 38, in inner
    response = await get_response(request)
  File "django/core/handlers/base.py", line 233, in _get_response_async
    response = await wrapped_callback(request, *callback_args, **callback_kwargs)
  File "asgiref/sync.py", line 444, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "asyncio/tasks.py", line 442, in wait_for
    return await fut
  File "asgiref/current_thread_executor.py", line 22, in run
    result = self.fn(*self.args, **self.kwargs)
  File "asgiref/sync.py", line 486, in thread_handler
    return func(*args, **kwargs)
  File "django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "django/views/decorators/debug.py", line 89, in sensitive_post_parameters_wrapper
    return view(request, *args, **kwargs)
  File "oauth2_provider/views/base.py", line 264, in post
    token = get_access_token_model().objects.get(token=access_token)
  File "django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "django/db/models/query.py", line 435, in get
    raise self.model.DoesNotExist(

My call looks like that:

curl -L -X POST 'https://my-server.com/oidc/token/' \
-F 'client_id="062191"' \
-F 'username="some-tester@byom.de"' \
-F 'password="P4ssw0rd"' \
-F 'grant_type="password"' \
-F 'scope="openid profile email address organization groups"'

I can only guess right now, but I think we run here into a problem with Django's move towards ASGI and the asynchronous nature of it.

ZuSe commented 3 years ago

Some additional information. I were able to reproduce it on local. What matters is the RTT to the database, when using my local PSQL it took me close to a thousand requests to run into it. Using a cloud-db with longer RTT (approx 200ms) it only took me 5-10 tries.

ViokingTung commented 1 year ago

i run uwsgi with multiple workers,still have this problem

Natgho commented 7 months ago

Problem is still exists.