Remove DOP dispatching from oauth_dispatch.

https://openedx.atlassian.net/browse/BOM-1330
This commit is contained in:
jinder1s
2020-02-26 11:40:28 -05:00
committed by Diana Huang
parent fe22e77072
commit 295da79fe5
15 changed files with 117 additions and 889 deletions

View File

@@ -14,45 +14,6 @@ from openedx.core.djangoapps.oauth_dispatch.tests.constants import DUMMY_REDIREC
from ..views import DOTAccessTokenExchangeView
class DOPAdapterMixin(object):
"""
Mixin to rewire existing tests to use django-oauth2-provider (DOP) backend
Overwrites self.client_id, self.access_token, self.oauth2_adapter
"""
client_id = 'dop_test_client_id'
access_token = 'dop_test_access_token'
oauth2_adapter = adapters.DOPAdapter()
def create_public_client(self, user, client_id=None):
"""
Create an oauth client application that is public.
"""
return self.oauth2_adapter.create_public_client(
name='Test Public Client',
user=user,
client_id=client_id,
redirect_uri=DUMMY_REDIRECT_URL,
)
def create_confidential_client(self, user, client_id=None):
"""
Create an oauth client application that is confidential.
"""
return self.oauth2_adapter.create_confidential_client(
name='Test Confidential Client',
user=user,
client_id=client_id,
redirect_uri=DUMMY_REDIRECT_URL,
)
def get_token_response_keys(self):
"""
Return the set of keys provided when requesting an access token
"""
return {'access_token', 'token_type', 'expires_in', 'scope'}
class DOTAdapterMixin(object):
"""
Mixin to rewire existing tests to use django-oauth-toolkit (DOT) backend

View File

@@ -3,5 +3,4 @@ Adapters to provide a common interface to django-oauth2-provider (DOP) and
django-oauth-toolkit (DOT).
"""
from .dop import DOPAdapter
from .dot import DOTAdapter

View File

@@ -1,89 +0,0 @@
"""
Adapter to isolate django-oauth2-provider dependencies
"""
from provider import constants, scope
from provider.oauth2 import models
class DOPAdapter(object):
"""
Standard interface for working with django-oauth2-provider
"""
backend = object()
def create_confidential_client(self, name, user, redirect_uri, client_id=None):
"""
Create an oauth client application that is confidential.
"""
return models.Client.objects.create(
name=name,
user=user,
client_id=client_id,
redirect_uri=redirect_uri,
client_type=constants.CONFIDENTIAL,
)
def create_public_client(self, name, user, redirect_uri, client_id=None):
"""
Create an oauth client application that is public.
"""
return models.Client.objects.create(
name=name,
user=user,
client_id=client_id,
redirect_uri=redirect_uri,
client_type=constants.PUBLIC,
)
def get_client(self, **filters):
"""
Get the oauth client application with the specified filters.
Wraps django's queryset.get() method.
"""
return models.Client.objects.get(**filters)
def get_client_for_token(self, token):
"""
Given an AccessToken object, return the associated client application.
"""
return token.client
def get_access_token(self, token_string):
"""
Given a token string, return the matching AccessToken object.
"""
return models.AccessToken.objects.get(token=token_string)
def create_access_token_for_test(self, token_string, client, user, expires):
"""
Returns a new AccessToken object created from the given arguments.
This method is currently used only by tests.
"""
return models.AccessToken.objects.create(
token=token_string,
client=client,
user=user,
expires=expires,
)
def get_token_scope_names(self, token):
"""
Given an access token object, return its scopes.
"""
return scope.to_names(token.scope)
def is_client_restricted(self, client): # pylint: disable=unused-argument
"""
Returns true if the client is set up as a RestrictedApplication.
"""
return False
def get_authorization_filters(self, client): # pylint: disable=unused-argument
"""
Get the authorization filters for the given client application.
"""
return []

View File

@@ -5,16 +5,12 @@ from oauth2_provider.models import AccessToken as dot_access_token
from oauth2_provider.models import RefreshToken as dot_refresh_token
from oauth2_provider.settings import oauth2_settings as dot_settings
from oauthlib.oauth2.rfc6749.tokens import BearerToken
from provider.oauth2.models import AccessToken as dop_access_token
from provider.oauth2.models import RefreshToken as dop_refresh_token
def destroy_oauth_tokens(user):
"""
Destroys ALL OAuth access and refresh tokens for the given user.
"""
dop_access_token.objects.filter(user=user.id).delete()
dop_refresh_token.objects.filter(user=user.id).delete()
dot_access_token.objects.filter(user=user.id).delete()
dot_refresh_token.objects.filter(user=user.id).delete()

View File

@@ -1,78 +0,0 @@
"""
Tests for DOP Adapter
"""
from datetime import timedelta
import ddt
from django.test import TestCase
from django.utils.timezone import now
from provider import constants
from provider.oauth2 import models
from student.tests.factories import UserFactory
from ..adapters import DOPAdapter
from .constants import DUMMY_REDIRECT_URL
@ddt.ddt
class DOPAdapterTestCase(TestCase):
"""
Test class for DOPAdapter.
"""
adapter = DOPAdapter()
def setUp(self):
super(DOPAdapterTestCase, self).setUp()
self.user = UserFactory()
self.public_client = self.adapter.create_public_client(
name='public client',
user=self.user,
redirect_uri=DUMMY_REDIRECT_URL,
client_id='public-client-id',
)
self.confidential_client = self.adapter.create_confidential_client(
name='confidential client',
user=self.user,
redirect_uri=DUMMY_REDIRECT_URL,
client_id='confidential-client-id',
)
@ddt.data(
('confidential', constants.CONFIDENTIAL),
('public', constants.PUBLIC),
)
@ddt.unpack
def test_create_client(self, client_name, client_type):
client = getattr(self, '{}_client'.format(client_name))
self.assertIsInstance(client, models.Client)
self.assertEqual(client.client_id, '{}-client-id'.format(client_name))
self.assertEqual(client.client_type, client_type)
def test_get_client(self):
client = self.adapter.get_client(client_type=constants.CONFIDENTIAL)
self.assertIsInstance(client, models.Client)
self.assertEqual(client.client_type, constants.CONFIDENTIAL)
def test_get_client_not_found(self):
with self.assertRaises(models.Client.DoesNotExist):
self.adapter.get_client(client_id='not-found')
def test_get_client_for_token(self):
token = models.AccessToken(
user=self.user,
client=self.public_client,
)
self.assertEqual(self.adapter.get_client_for_token(token), self.public_client)
def test_get_access_token(self):
token = self.adapter.create_access_token_for_test(
'token-id',
client=self.public_client,
user=self.user,
expires=now() + timedelta(days=30),
)
self.assertEqual(self.adapter.get_access_token(token_string='token-id'), token)

View File

@@ -10,7 +10,7 @@ from django.utils.timezone import now
from mock import patch
from openedx.core.djangoapps.oauth_dispatch import jwt as jwt_api
from openedx.core.djangoapps.oauth_dispatch.adapters import DOPAdapter, DOTAdapter
from openedx.core.djangoapps.oauth_dispatch.adapters import DOTAdapter
from openedx.core.djangoapps.oauth_dispatch.models import RestrictedApplication
from openedx.core.djangoapps.oauth_dispatch.tests.mixins import AccessTokenMixin
from openedx.core.djangoapps.oauth_dispatch.toggles import ENFORCE_JWT_SCOPES
@@ -61,9 +61,8 @@ class TestCreateJWTs(AccessTokenMixin, TestCase):
jwt_token, self.user, self.default_scopes, should_be_asymmetric_key=should_be_asymmetric_key,
)
@ddt.data(DOPAdapter, DOPAdapter)
def test_create_jwt_for_token(self, oauth_adapter_cls):
oauth_adapter = oauth_adapter_cls()
def test_create_jwt_for_token(self):
oauth_adapter = DOTAdapter()
jwt_token = self._create_jwt_for_token(oauth_adapter, use_asymmetric_key=False)
self._assert_jwt_is_valid(jwt_token, should_be_asymmetric_key=False)

View File

@@ -15,7 +15,6 @@ from django.urls import reverse
from jwkest import jwk
from mock import call, patch
from oauth2_provider import models as dot_models
from provider import constants
from openedx.core.djangoapps.oauth_dispatch.toggles import ENFORCE_JWT_SCOPES
from student.tests.factories import UserFactory
@@ -86,7 +85,6 @@ class _DispatchingViewTestCase(TestCase):
"""
def setUp(self):
super(_DispatchingViewTestCase, self).setUp()
self.dop_adapter = adapters.DOPAdapter()
self.dot_adapter = adapters.DOTAdapter()
self.user = UserFactory()
self.dot_app = self.dot_adapter.create_public_client(
@@ -95,12 +93,6 @@ class _DispatchingViewTestCase(TestCase):
redirect_uri=DUMMY_REDIRECT_URL,
client_id='dot-app-client-id',
)
self.dop_app = self.dop_adapter.create_public_client(
name='test dop client',
user=self.user,
redirect_uri=DUMMY_REDIRECT_URL,
client_id='dop-app-client-id',
)
self.dot_app_access = models.ApplicationAccess.objects.create(
application=self.dot_app,
@@ -197,7 +189,7 @@ class TestAccessTokenView(AccessTokenLoginMixin, mixins.AccessTokenMixin, _Dispa
should_be_restricted=False,
)
@ddt.data('dop_app', 'dot_app')
@ddt.data('dot_app')
def test_access_token_fields(self, client_attr):
client = getattr(self, client_attr)
response = self._post_request(self.user, client)
@@ -227,15 +219,15 @@ class TestAccessTokenView(AccessTokenLoginMixin, mixins.AccessTokenMixin, _Dispa
True
)
@ddt.data('dop_app', 'dot_app')
@ddt.data('dot_app')
def test_jwt_access_token_from_parameter(self, client_attr):
self._test_jwt_access_token(client_attr, token_type='jwt')
@ddt.data('dop_app', 'dot_app')
@ddt.data('dot_app')
def test_jwt_access_token_from_header(self, client_attr):
self._test_jwt_access_token(client_attr, headers={'HTTP_X_TOKEN_TYPE': 'jwt'})
@ddt.data('dop_app', 'dot_app')
@ddt.data('dot_app')
def test_jwt_access_token_from_parameter_not_header(self, client_attr):
self._test_jwt_access_token(client_attr, token_type='jwt', headers={'HTTP_X_TOKEN_TYPE': 'invalid'})
@@ -261,7 +253,7 @@ class TestAccessTokenView(AccessTokenLoginMixin, mixins.AccessTokenMixin, _Dispa
'grant_type': grant_type.replace('-', '_'),
}
bad_response = self.client.post(self.url, invalid_body)
self.assertEqual(bad_response.status_code, 400)
self.assertEqual(bad_response.status_code, 401)
expected_calls = [
call('oauth_token_type', 'no_token_type_supplied'),
call('oauth_grant_type', 'password'),
@@ -322,12 +314,6 @@ class TestAccessTokenView(AccessTokenLoginMixin, mixins.AccessTokenMixin, _Dispa
data = json.loads(response.content.decode('utf-8'))
self.assertIn('refresh_token', data)
def test_dop_public_client_access_token(self):
response = self._post_request(self.user, self.dop_app)
self.assertEqual(response.status_code, 200)
data = json.loads(response.content.decode('utf-8'))
self.assertNotIn('refresh_token', data)
@ddt.data(dot_models.Application.GRANT_CLIENT_CREDENTIALS, dot_models.Application.GRANT_PASSWORD)
def test_jwt_access_token_scopes_and_filters(self, grant_type):
"""
@@ -396,7 +382,6 @@ class TestAuthorizationView(_DispatchingViewTestCase):
def setUp(self):
super(TestAuthorizationView, self).setUp()
self.dop_adapter = adapters.DOPAdapter()
self.user = UserFactory()
self.dot_app = self.dot_adapter.create_confidential_client(
name='test dot application',
@@ -412,16 +397,10 @@ class TestAuthorizationView(_DispatchingViewTestCase):
'other_filter:filter_val',
]
)
self.dop_app = self.dop_adapter.create_confidential_client(
name='test dop client',
user=self.user,
redirect_uri=DUMMY_REDIRECT_URL,
client_id='confidential-dop-app-client-id',
)
@ddt.data(
('dop', 'authorize'),
('dot', 'allow')
('dot', 'allow'),
('dot', 'authorize')
)
@ddt.unpack
def test_post_authorization_view(self, client_type, allow_field):
@@ -506,23 +485,6 @@ class TestAuthorizationView(_DispatchingViewTestCase):
expected_redirect_prefix = u'{}?'.format(DUMMY_REDIRECT_URL)
self._assert_startswith(self._redirect_destination(response), expected_redirect_prefix)
def _check_dop_response(self, response):
"""
Check that django-oauth2-provider gives an appropriate authorization response.
"""
# django-oauth-provider redirects to a confirmation page
self.assertRedirects(response, u'/oauth2/authorize/confirm', target_status_code=200)
context = response.context_data
form = context['form']
self.assertIsNone(form['authorize'].value())
oauth_data = context['oauth_data']
self.assertEqual(oauth_data['redirect_uri'], DUMMY_REDIRECT_URL)
self.assertEqual(oauth_data['state'], 'random_state_string')
# TODO: figure out why it chooses this scope.
self.assertEqual(oauth_data['scope'], constants.READ_WRITE)
def _assert_startswith(self, string, prefix):
"""
Assert that the string starts with the specified prefix.
@@ -545,16 +507,9 @@ class TestViewDispatch(TestCase):
def setUp(self):
super(TestViewDispatch, self).setUp()
self.dop_adapter = adapters.DOPAdapter()
self.dot_adapter = adapters.DOTAdapter()
self.user = UserFactory()
self.view = views._DispatchingView() # pylint: disable=protected-access
self.dop_adapter.create_public_client(
name='',
user=self.user,
client_id='dop-id',
redirect_uri=DUMMY_REDIRECT_URL
)
self.dot_adapter.create_public_client(
name='',
user=self.user,
@@ -589,54 +544,26 @@ class TestViewDispatch(TestCase):
"""
return RequestFactory().get('/?client_id={}'.format(client_id))
def _verify_oauth_metrics_calls(self, mock_set_custom_metric, expected_oauth_adapter):
"""
Args:
mock_set_custom_metric: MagicMock of set_custom_metric
expected_oauth_adapter: Either 'dot' or 'dop'
"""
expected_calls = [
call('oauth_client_id', '{}-id'.format(expected_oauth_adapter)),
call('oauth_adapter', expected_oauth_adapter),
]
mock_set_custom_metric.assert_has_calls(expected_calls, any_order=True)
@patch('edx_django_utils.monitoring.set_custom_metric')
def test_dispatching_post_to_dot(self, mock_set_custom_metric):
def test_dispatching_post_to_dot(self):
request = self._post_request('dot-id')
self.assertEqual(self.view.select_backend(request), self.dot_adapter.backend)
self._verify_oauth_metrics_calls(mock_set_custom_metric, 'dot')
@patch('edx_django_utils.monitoring.set_custom_metric')
def test_dispatching_post_to_dop(self, mock_set_custom_metric):
request = self._post_request('dop-id')
self.assertEqual(self.view.select_backend(request), self.dop_adapter.backend)
self._verify_oauth_metrics_calls(mock_set_custom_metric, 'dop')
def test_dispatching_get_to_dot(self):
request = self._get_request('dot-id')
self.assertEqual(self.view.select_backend(request), self.dot_adapter.backend)
def test_dispatching_get_to_dop(self):
request = self._get_request('dop-id')
self.assertEqual(self.view.select_backend(request), self.dop_adapter.backend)
def test_dispatching_with_no_client(self):
request = self._post_request(None)
self.assertEqual(self.view.select_backend(request), self.dop_adapter.backend)
self.assertEqual(self.view.select_backend(request), self.dot_adapter.backend)
def test_dispatching_with_invalid_client(self):
request = self._post_request('abcesdfljh')
self.assertEqual(self.view.select_backend(request), self.dop_adapter.backend)
self.assertEqual(self.view.select_backend(request), self.dot_adapter.backend)
def test_get_view_for_dot(self):
view_object = views.AccessTokenView()
self.assert_is_view(view_object.get_view_for_backend(self.dot_adapter.backend))
def test_get_view_for_dop(self):
view_object = views.AccessTokenView()
self.assert_is_view(view_object.get_view_for_backend(self.dop_adapter.backend))
def test_get_view_for_no_backend(self):
view_object = views.AccessTokenView()
self.assertRaises(KeyError, view_object.get_view_for_backend, None)

View File

@@ -10,8 +10,6 @@ from django.conf import settings
from django.utils.decorators import method_decorator
from django.views.generic import View
from edx_django_utils import monitoring as monitoring_utils
from edx_oauth2_provider import views as dop_views # django-oauth2-provider views
from oauth2_provider import models as dot_models # django-oauth-toolkit
from oauth2_provider import views as dot_views
from ratelimit import ALL
from ratelimit.decorators import ratelimit
@@ -30,7 +28,6 @@ class _DispatchingView(View):
"""
dot_adapter = adapters.DOTAdapter()
dop_adapter = adapters.DOPAdapter()
def get_adapter(self, request):
"""
@@ -39,12 +36,7 @@ class _DispatchingView(View):
client_id = self._get_client_id(request)
monitoring_utils.set_custom_metric('oauth_client_id', client_id)
if dot_models.Application.objects.filter(client_id=client_id).exists() or not settings.ENABLE_DOP_ADAPTER:
monitoring_utils.set_custom_metric('oauth_adapter', 'dot')
return self.dot_adapter
else:
monitoring_utils.set_custom_metric('oauth_adapter', 'dop')
return self.dop_adapter
return self.dot_adapter
def dispatch(self, request, *args, **kwargs):
"""
@@ -69,11 +61,7 @@ class _DispatchingView(View):
Return the appropriate view from the requested backend.
"""
if backend == self.dot_adapter.backend:
monitoring_utils.set_custom_metric('oauth_view', 'dot')
return self.dot_view.as_view()
elif backend == self.dop_adapter.backend:
monitoring_utils.set_custom_metric('oauth_view', 'dop')
return self.dop_view.as_view()
else:
raise KeyError('Failed to dispatch view. Invalid backend {}'.format(backend))
@@ -98,7 +86,6 @@ class AccessTokenView(_DispatchingView):
Handle access token requests.
"""
dot_view = dot_views.TokenView
dop_view = dop_views.AccessTokenView
def dispatch(self, request, *args, **kwargs):
response = super(AccessTokenView, self).dispatch(request, *args, **kwargs)
@@ -128,7 +115,6 @@ class AuthorizationView(_DispatchingView):
"""
Part of the authorization flow.
"""
dop_view = dop_views.Capture
dot_view = dot_overrides_views.EdxOAuth2AuthorizationView
@@ -138,19 +124,6 @@ class AccessTokenExchangeView(_DispatchingView):
"""
dot_view = auth_exchange_views.DOTAccessTokenExchangeView
def get_view_for_backend(self, backend):
"""
Return the appropriate view from the requested backend.
Since AccessTokenExchangeView no longer supports dop, this function needed to
be overwritten from _DispatchingView, it was decided that the dop path should not be removed
from _DispatchingView due to it still being used in other views(AuthorizationView, AccessTokenView)
"""
if backend == self.dot_adapter.backend:
monitoring_utils.set_custom_metric('oauth_view', 'dot')
return self.dot_view.as_view()
else:
raise KeyError('Failed to dispatch view. Invalid backend {}'.format(backend))
class RevokeTokenView(_DispatchingView):
"""

View File

@@ -68,7 +68,6 @@ class OAuth2AllowInActiveUsersTests(TestCase):
def setUp(self):
super(OAuth2AllowInActiveUsersTests, self).setUp()
self.dop_adapter = adapters.DOPAdapter()
self.dot_adapter = adapters.DOTAdapter()
self.csrf_client = APIClient(enforce_csrf_checks=True)
self.username = 'john'
@@ -76,29 +75,6 @@ class OAuth2AllowInActiveUsersTests(TestCase):
self.password = 'password'
self.user = User.objects.create_user(self.username, self.email, self.password)
self.CLIENT_ID = 'client_key' # pylint: disable=invalid-name
self.CLIENT_SECRET = 'client_secret' # pylint: disable=invalid-name
self.ACCESS_TOKEN = 'access_token' # pylint: disable=invalid-name
self.REFRESH_TOKEN = 'refresh_token' # pylint: disable=invalid-name
self.dop_oauth2_client = self.dop_adapter.create_public_client(
name='example',
user=self.user,
client_id=self.CLIENT_ID,
redirect_uri='https://example.edx/redirect',
)
self.access_token = oauth2_provider.oauth2.models.AccessToken.objects.create(
token=self.ACCESS_TOKEN,
client=self.dop_oauth2_client,
user=self.user,
)
self.refresh_token = oauth2_provider.oauth2.models.RefreshToken.objects.create(
user=self.user,
access_token=self.access_token,
client=self.dop_oauth2_client,
)
self.dot_oauth2_client = self.dot_adapter.create_public_client(
name='example',
user=self.user,
@@ -111,6 +87,11 @@ class OAuth2AllowInActiveUsersTests(TestCase):
application=self.dot_oauth2_client,
expires=now() + timedelta(days=30),
)
self.dot_refresh_token = dot_models.RefreshToken.objects.create(
user=self.user,
token='dot-refresh-token',
application=self.dot_oauth2_client,
)
# This is the a change we've made from the django-rest-framework-oauth version
# of these tests.
@@ -125,6 +106,11 @@ class OAuth2AllowInActiveUsersTests(TestCase):
# edx-auth2-provider.
scope.SCOPE_NAME_DICT = {'read': constants.READ, 'write': constants.WRITE}
def _create_authorization_header(self, token=None):
if token is None:
token = self.dot_access_token.token
return "Bearer {0}".format(token)
def get_with_bearer_token(self, target_url, params=None, token=None):
"""
Make a GET request to the specified URL with an OAuth2 bearer token. If
@@ -151,11 +137,6 @@ class OAuth2AllowInActiveUsersTests(TestCase):
self.assertEqual(response.status_code, status_code)
self.assertEqual(response_dict['error_code'], error_code)
def _create_authorization_header(self, token=None):
if token is None:
token = self.access_token.token
return "Bearer {0}".format(token)
@ddt.data(None, {})
@unittest.skipUnless(oauth2_provider, 'django-oauth2-provider not installed')
def test_get_form_with_wrong_authorization_header_token_type_failing(self, params):
@@ -173,18 +154,13 @@ class OAuth2AllowInActiveUsersTests(TestCase):
# provided (yet).
self.assertNotIn('error_code', json.loads(response.content.decode('utf-8')))
def test_get_form_passing_auth(self):
"""Ensure GETing form over OAuth with correct client credentials succeed"""
response = self.get_with_bearer_token(self.OAUTH2_BASE_TESTING_URL)
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_get_form_passing_auth_with_dot(self):
response = self.get_with_bearer_token(self.OAUTH2_BASE_TESTING_URL, token=self.dot_access_token.token)
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_get_form_failing_auth_url_transport(self):
"""Ensure GETing form over OAuth with correct client credentials in query fails when DEBUG is False"""
query = urlencode({'access_token': self.access_token.token})
query = urlencode({'access_token': self.dot_access_token.token})
response = self.csrf_client.get(self.OAUTH2_BASE_TESTING_URL + '?%s' % query)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
@@ -198,7 +174,7 @@ class OAuth2AllowInActiveUsersTests(TestCase):
def test_post_form_token_removed_failing_auth(self):
"""Ensure POSTing when there is no OAuth access token in db fails"""
self.access_token.delete()
self.dot_access_token.delete()
response = self.post_with_bearer_token(self.OAUTH2_BASE_TESTING_URL)
self.check_error_codes(
response,
@@ -208,7 +184,7 @@ class OAuth2AllowInActiveUsersTests(TestCase):
def test_post_form_with_refresh_token_failing_auth(self):
"""Ensure POSTing with refresh token instead of access token fails"""
response = self.post_with_bearer_token(self.OAUTH2_BASE_TESTING_URL, token=self.refresh_token.token)
response = self.post_with_bearer_token(self.OAUTH2_BASE_TESTING_URL, token=self.dot_refresh_token.token)
self.check_error_codes(
response,
status_code=status.HTTP_401_UNAUTHORIZED,
@@ -217,8 +193,8 @@ class OAuth2AllowInActiveUsersTests(TestCase):
def test_post_form_with_expired_access_token_failing_auth(self):
"""Ensure POSTing with expired access token fails with a 'token_expired' error"""
self.access_token.expires = now() - timedelta(seconds=10) # 10 seconds late
self.access_token.save()
self.dot_access_token.expires = now() - timedelta(seconds=10) # 10 seconds late
self.dot_access_token.save()
response = self.post_with_bearer_token(self.OAUTH2_BASE_TESTING_URL)
self.check_error_codes(
response,