class DOPAccessTokenExchangeView(AccessTokenExchangeBase, DOPAccessTokenView): """ View for token exchange from 3rd party OAuth access token to 1st party OAuth access token. Uses django-oauth2-provider (DOP) to manage access tokens. """ oauth2_adapter = adapters.DOPAdapter()
def setUp(self): super(OAuth2Tests, self).setUp() self.dop_adapter = adapters.DOPAdapter() self.dot_adapter = adapters.DOTAdapter() self.csrf_client = APIClient(enforce_csrf_checks=True) self.username = '******' self.email = '*****@*****.**' self.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, client_id='dot-client-id', redirect_uri='https://example.edx/redirect', ) self.dot_access_token = dot_models.AccessToken.objects.create( user=self.user, token='dot-access-token', application=self.dot_oauth2_client, expires=datetime.now() + timedelta(days=30), ) # This is the a change we've made from the django-rest-framework-oauth version # of these tests. self.user.is_active = False self.user.save() # This is the a change we've made from the django-rest-framework-oauth version # of these tests. # Override the SCOPE_NAME_DICT setting for tests for oauth2-with-scope-test. This is # needed to support READ and WRITE scopes as they currently aren't supported by the # edx-auth2-provider, and their scope values collide with other scopes defined in the # edx-auth2-provider. scope.SCOPE_NAME_DICT = {'read': constants.READ, 'write': constants.WRITE}
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 _DispatchingView(View): """ Base class that route views to the appropriate provider view. The default behavior routes based on client_id, but this can be overridden by redefining `select_backend()` if particular views need different behavior. """ dot_adapter = adapters.DOTAdapter() dop_adapter = adapters.DOPAdapter() def get_adapter(self, request): """ Returns the appropriate adapter based on the OAuth client linked to the request. """ 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(): 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 def dispatch(self, request, *args, **kwargs): """ Dispatch the request to the selected backend's view. """ backend = self.select_backend(request) view = self.get_view_for_backend(backend) return view(request, *args, **kwargs) def select_backend(self, request): """ Given a request that specifies an oauth `client_id`, return the adapter for the appropriate OAuth handling library. If the client_id is found in a django-oauth-toolkit (DOT) Application, use the DOT adapter, otherwise use the django-oauth2-provider (DOP) adapter, and allow the calls to fail normally if the client does not exist. """ return self.get_adapter(request).backend def get_view_for_backend(self, backend): """ Return the appropriate view from the requested backend. """ if backend == self.dot_adapter.backend: return self.dot_view.as_view() elif backend == self.dop_adapter.backend: return self.dop_view.as_view() else: raise KeyError( 'Failed to dispatch view. Invalid backend {}'.format(backend)) def _get_client_id(self, request): """ Return the client_id from the provided request """ if request.method == u'GET': return request.GET.get('client_id') else: return request.POST.get('client_id')