jazzband / django-oauth-toolkit

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

Column `source_refresh_token_id` of `oauth2_provider_accesstoken` does not exist #809

Closed mauroveron closed 4 years ago

mauroveron commented 4 years ago

Describe the bug I'm getting an error when creating a token that refers to a refresh token:

14.1.51.50 - - [11/Mar/2020 00:21:20] "GET /o/authorize/?state=<hidden>&redirect_uri=https%3A%2F%2Fmyapp.dev%2Flogin%2Foauth%2Fcallback%2F&response_type=code&client_id=QZQffAvhGPmiQz3gwv2HU0MYV61XrmCu5WubnEBw HTTP/1.1" 302 -
DEBUG 2020-03-11 00:21:22,097 oauthlib.oauth2.rfc6749.endpoints.token Dispatching grant_type authorization_code request to <oauthlib.oauth2.rfc6749.grant_types.authorization_code.AuthorizationCodeGrant object at 0x7f666c555f10>.
DEBUG 2020-03-11 00:21:22,131 oauthlib.oauth2.rfc6749.grant_types.authorization_code Using provided redirect_uri https://myapp.dev/login/oauth/callback/
DEBUG 2020-03-11 00:21:22,136 oauthlib.oauth2.rfc6749.grant_types.authorization_code Token request validation ok for <oauthlib.Request SANITIZED>.
14.1.51.50 - - [11/Mar/2020 00:21:22] "POST /o/token/ HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: column "source_refresh_token_id" of relation "oauth2_provider_accesstoken" does not exist
LINE 1: ...RT INTO "oauth2_provider_accesstoken" ("user_id", "source_re...
                                                             ^

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/venv/lib/python3.7/site-packages/django/contrib/staticfiles/handlers.py", line 65, in __call__
    return self.application(environ, start_response)
  File "/venv/lib/python3.7/site-packages/django/core/handlers/wsgi.py", line 141, in __call__
    response = self.get_response(request)
  File "/venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 75, in get_response
    response = self._middleware_chain(request)
  File "/venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
    response = response_for_exception(request, exc)
  File "/venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 125, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/venv/lib/python3.7/site-packages/django_extensions/management/technical_response.py", line 37, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/venv/lib/python3.7/site-packages/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib/python3.7/contextlib.py", line 74, in inner
    return func(*args, **kwds)
  File "/venv/lib/python3.7/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "/venv/lib/python3.7/site-packages/django/utils/decorators.py", line 45, in _wrapper
    return bound_method(*args, **kwargs)
  File "/venv/lib/python3.7/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/venv/lib/python3.7/site-packages/django/views/generic/base.py", line 97, in dispatch
    return handler(request, *args, **kwargs)
  File "/venv/lib/python3.7/site-packages/django/utils/decorators.py", line 45, in _wrapper
    return bound_method(*args, **kwargs)
  File "/venv/lib/python3.7/site-packages/django/views/decorators/debug.py", line 76, in sensitive_post_parameters_wrapper
    return view(request, *args, **kwargs)
  File "/venv/lib/python3.7/site-packages/oauth2_provider/views/base.py", line 260, in post
    url, headers, body, status = self.create_token_response(request)
  File "/venv/lib/python3.7/site-packages/oauth2_provider/views/mixins.py", line 124, in create_token_response
    return core.create_token_response(request)
  File "/venv/lib/python3.7/site-packages/oauth2_provider/oauth2_backends.py", line 145, in create_token_response
    headers, extra_credentials)
  File "/venv/lib/python3.7/site-packages/oauthlib/oauth2/rfc6749/endpoints/base.py", line 116, in wrapper
    return f(endpoint, uri, *args, **kwargs)
  File "/venv/lib/python3.7/site-packages/oauthlib/oauth2/rfc6749/endpoints/token.py", line 119, in create_token_response
    request, self.default_token_type)
  File "/venv/lib/python3.7/site-packages/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py", line 313, in create_token_response
    self.request_validator.save_token(token, request)
  File "/venv/lib/python3.7/site-packages/oauthlib/oauth2/rfc6749/request_validator.py", line 306, in save_token
    return self.save_bearer_token(token, request, *args, **kwargs)
  File "/usr/lib/python3.7/contextlib.py", line 74, in inner
    return func(*args, **kwds)
  File "/venv/lib/python3.7/site-packages/oauth2_provider/oauth2_validators.py", line 548, in save_bearer_token
    source_refresh_token=refresh_token_instance,
  File "/venv/lib/python3.7/site-packages/oauth2_provider/oauth2_validators.py", line 572, in _create_access_token
    source_refresh_token=source_refresh_token,
  File "/venv/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/venv/lib/python3.7/site-packages/django/db/models/query.py", line 422, in create
    obj.save(force_insert=True, using=self.db)
  File "/venv/lib/python3.7/site-packages/django/db/models/base.py", line 741, in save
    force_update=force_update, update_fields=update_fields)
  File "/venv/lib/python3.7/site-packages/django/db/models/base.py", line 779, in save_base
    force_update, using, update_fields,
  File "/venv/lib/python3.7/site-packages/django/db/models/base.py", line 870, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/venv/lib/python3.7/site-packages/django/db/models/base.py", line 908, in _do_insert
    using=using, raw=raw)
  File "/venv/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/venv/lib/python3.7/site-packages/django/db/models/query.py", line 1186, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1368, in execute_sql
    cursor.execute(sql, params)
  File "/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 99, in execute
    return super().execute(sql, params)
  File "/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/venv/lib/python3.7/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: column "source_refresh_token_id" of relation "oauth2_provider_accesstoken" does not exist
LINE 1: ...RT INTO "oauth2_provider_accesstoken" ("user_id", "source_re...
                                                             ^

This started happening after an upgrade to 1.3.0 from 1.0.0.

I was able to track down the missing column to the squashed migration 0001 here

I'm not sure if the column should be re-introduced or the code that refers to the refresh token should be updated?

To Reproduce The app just does a GET request to the /authorize endpoint and then POST request to the /token endpoint, with the following details:

{
u'client_id': u'QZQffAvhGPmiQz3gwv2HU0MYV61XrmCu5WubnEBw',
u'client_secret': u'THE_SECRET',
u'code': u'RAoSfks5cA0FZomN6Tnmc7lkyAk0K4',
u'grant_type': u'authorization_code',
u'redirect_uri': 'https://myapp.dev/login/oauth/callback/'
}

This is where the error with the source_refresh_token_id happens

Expected behavior I should get the access token

Version 1.3.0 after an upgrade from 1.0.0

n2ygk commented 4 years ago

Please see the changelog warning about this:

You unfortunately have to first install 1.2.0 and do this:

manage.py makemigrations
manage.py migrate

Then you can install 1.3.0 and do it again:

manage.py makemigrations
manage.py migrate
supunsandeeptha commented 2 years ago

The above approach helps with 2.0.0 version as well

kstopa commented 10 months ago

In my case I couldn't go back and forth to 1.2 and 1.3 (as I was already with 2.3 on production after updating Django (long story.....)). In any case adding the columns manually using SQL (in postgres) as in the migrations on 1.2 make my day:

ALTER TABLE oauth2_provider_accesstoken ADD COLUMN source_refresh_token_id INTEGER REFERENCES oauth2_provider_refreshtoken(id) ON DELETE SET NULL;
ALTER TABLE oauth2_provider_refreshtoken ADD COLUMN revoked TIMESTAMP WITH TIME ZONE;
ALTER TABLE oauth2_provider_refreshtoken ALTER COLUMN revoked SET DEFAULT NULL;