Ejemplo n.º 1
0
class DOTAdapterMixin(object):
    """
    Mixin to rewire existing tests to use django-oauth-toolkit (DOT) backend

    Overwrites self.client_id, self.access_token, self.oauth2_adapter
    """

    client_id = 'dot_test_client_id'
    access_token = 'dot_test_access_token'
    oauth2_adapter = adapters.DOTAdapter()

    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 Application',
            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 Application',
            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', 'refresh_token', 'token_type', 'expires_in',
            'scope'
        }

    def test_get_method(self):
        # Dispatch routes all get methods to DOP, so we test this on the view
        request_factory = RequestFactory()
        request = request_factory.get('/oauth2/exchange_access_token/')
        request.session = {}
        view = DOTAccessTokenExchangeView.as_view()
        response = view(request, backend='facebook')
        self.assertEqual(response.status_code, 400)

    @expectedFailure
    def test_single_access_token(self):
        # TODO: Single access tokens not supported yet for DOT (See MA-2122)
        super(DOTAdapterMixin, self).test_single_access_token()

    @skip("Not supported yet (See MA-2123)")
    def test_scopes(self):
        super(DOTAdapterMixin, self).test_scopes()
    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}
Ejemplo n.º 3
0
class DOTAccessTokenExchangeView(AccessTokenExchangeBase, DOTAccessTokenView):
    """
    View for token exchange from 3rd party OAuth access token to 1st party
    OAuth access token.  Uses django-oauth-toolkit (DOT) to manage access
    tokens.
    """

    oauth2_adapter = adapters.DOTAdapter()

    def get(self, request, _backend):
        return Response(status=400,
                        data={
                            'error': 'invalid_request',
                            'error_description': 'Only POST requests allowed.',
                        })

    def get_access_token(self, request, user, scope, client):
        """
        TODO: MA-2122: Reusing access tokens is not yet supported for DOT.
        Just return a new access token.
        """
        return self.create_access_token(request, user, scope, client)

    def create_access_token(self, request, user, scope, client):
        """
        Create and return a new access token.
        """
        _days = 24 * 60 * 60
        token_generator = BearerToken(
            expires_in=settings.OAUTH_EXPIRE_PUBLIC_CLIENT_DAYS * _days,
            request_validator=oauth2_settings.OAUTH2_VALIDATOR_CLASS(),
        )
        self._populate_create_access_token_request(request, user, scope,
                                                   client)
        return token_generator.create_token(request, refresh_token=True)

    def access_token_response(self, token):
        """
        Wrap an access token in an appropriate response
        """
        return Response(data=token)

    def _populate_create_access_token_request(self, request, user, scope,
                                              client):
        """
        django-oauth-toolkit expects certain non-standard attributes to
        be present on the request object.  This function modifies the
        request object to match these expectations
        """
        request.user = user
        request.scopes = [SCOPE_VALUE_DICT[scope]]
        request.client = client
        request.state = None
        request.refresh_token = None
        request.extra_credentials = None
        request.grant_type = client.authorization_grant_type

    def error_response(self, form_errors):
        """
        Return an error response consisting of the errors in the form
        """
        return Response(status=400, data=form_errors)