Esempio n. 1
0
    def test_code_exchange_fails_when_redirect_uri_does_not_match(self):
        """
        Tests code exchange fails when redirect uri does not match the one used for code request
        """
        self.client.login(username="******", password="******")

        # retrieve a valid authorization code
        authcode_data = {
            'client_id': self.application.client_id,
            'state': 'random_state_string',
            'scope': 'read write',
            'redirect_uri': 'http://example.it?foo=bar',
            'response_type': 'code',
            'allow': True,
        }
        response = self.client.post(reverse('oauth2_provider:authorize'),
                                    data=authcode_data)
        query_dict = parse_qs(urlparse(response['Location']).query)
        authorization_code = query_dict['code'].pop()

        # exchange authorization code for a valid access token
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it?foo=baraa'
        }
        auth_headers = get_basic_auth_header(self.application.client_id,
                                             self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 401)
Esempio n. 2
0
    def test_refresh_invalidates_old_tokens(self):
        """
        Ensure existing refresh tokens are cleaned up when issuing new ones
        """
        self.client.login(username="******", password="******")
        authorization_code = self.get_auth()

        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it'
        }
        auth_headers = get_basic_auth_header(self.application.client_id,
                                             self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        content = json.loads(response.content.decode("utf-8"))

        rt = content['refresh_token']
        at = content['access_token']

        token_request_data = {
            'grant_type': 'refresh_token',
            'refresh_token': rt,
            'scope': content['scope'],
        }
        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 200)

        self.assertFalse(RefreshToken.objects.filter(token=rt).exists())
        self.assertFalse(AccessToken.objects.filter(token=at).exists())
Esempio n. 3
0
    def test_refresh_bad_scopes(self):
        """
        Request an access token using a refresh token and wrong scopes
        """
        self.client.login(username="******", password="******")
        authorization_code = self.get_auth()

        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it'
        }
        auth_headers = get_basic_auth_header(self.application.client_id,
                                             self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        content = json.loads(response.content.decode("utf-8"))
        self.assertTrue('refresh_token' in content)

        token_request_data = {
            'grant_type': 'refresh_token',
            'refresh_token': content['refresh_token'],
            'scope': 'read write nuke',
        }
        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 401)
Esempio n. 4
0
    def test_refresh_fail_repeating_requests(self):
        """
        Try refreshing an access token with the same refresh token more than once
        """
        self.client.login(username="******", password="******")
        authorization_code = self.get_auth()

        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it'
        }
        auth_headers = get_basic_auth_header(self.application.client_id,
                                             self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        content = json.loads(response.content.decode("utf-8"))
        self.assertTrue('refresh_token' in content)

        token_request_data = {
            'grant_type': 'refresh_token',
            'refresh_token': content['refresh_token'],
            'scope': content['scope'],
        }
        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 200)
        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 401)
Esempio n. 5
0
    def get_access_token(self, scopes):
        self.client.login(username="******", password="******")

        # retrieve a valid authorization code
        authcode_data = {
            'client_id': self.application.client_id,
            'state': 'random_state_string',
            'scope': scopes,
            'redirect_uri': 'http://example.it',
            'response_type': 'code',
            'allow': True,
        }
        response = self.client.post(reverse('oauth2_provider:authorize'),
                                    data=authcode_data)
        query_dict = parse_qs(urlparse(response['Location']).query)
        authorization_code = query_dict['code'].pop()

        # exchange authorization code for a valid access token
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it'
        }
        auth_headers = self.get_basic_auth_header(
            self.application.client_id, self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        content = json.loads(response.content.decode("utf-8"))
        return content['access_token']
    def test_code_exchange_succeed_when_redirect_uri_match(self):
        """
        Tests code exchange succeed when redirect uri matches the one used for code request
        """
        self.client.login(username="******", password="******")

        # retrieve a valid authorization code
        authcode_data = {
            'client_id': self.application.client_id,
            'state': 'random_state_string',
            'scope': 'read write',
            'redirect_uri': 'http://example.it?foo=bar',
            'response_type': 'code',
            'allow': True,
        }
        response = self.client.post(reverse('oauth2_provider:authorize'), data=authcode_data)
        query_dict = parse_qs(urlparse(response['Location']).query)
        authorization_code = query_dict['code'].pop()

        # exchange authorization code for a valid access token
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it?foo=bar'
        }
        auth_headers = self.get_basic_auth_header(self.application.client_id, self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
        self.assertEqual(response.status_code, 200)

        content = json.loads(response.content.decode("utf-8"))
        self.assertEqual(content['token_type'], "Bearer")
        self.assertEqual(content['scope'], "read write")
        self.assertEqual(content['expires_in'], oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS)
Esempio n. 7
0
    def test_scopes_save_in_access_token(self):
        """
        Test scopes are properly saved in access token
        """
        self.client.login(username="******", password="******")

        # retrieve a valid authorization code
        authcode_data = {
            'client_id': self.application.client_id,
            'state': 'random_state_string',
            'scope': 'scope1 scope2',
            'redirect_uri': 'http://example.it',
            'response_type': 'code',
            'allow': True,
        }
        response = self.client.post(reverse('oauth2_provider:authorize'), data=authcode_data)
        query_dict = parse_qs(urlparse(response['Location']).query)
        authorization_code = query_dict['code'].pop()

        # exchange authorization code for a valid access token
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it'
        }
        auth_headers = get_basic_auth_header(self.application.client_id, self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
        content = json.loads(response.content.decode("utf-8"))
        access_token = content['access_token']

        at = AccessToken.objects.get(token=access_token)
        self.assertEqual(at.scope, "scope1 scope2")
Esempio n. 8
0
    def test_refresh(self):
        """
        Request an access token using a refresh token
        """
        self.client.login(username="******", password="******")
        authorization_code = self.get_auth()

        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it'
        }
        auth_headers = get_basic_auth_header(self.application.client_id,
                                             self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        content = json.loads(response.content.decode("utf-8"))
        self.assertTrue('refresh_token' in content)

        # make a second token request to be sure the previous refresh token remains valid, see #65
        authorization_code = self.get_auth()
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it'
        }
        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)

        token_request_data = {
            'grant_type': 'refresh_token',
            'refresh_token': content['refresh_token'],
            'scope': content['scope'],
        }
        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 200)

        content = json.loads(response.content.decode("utf-8"))
        self.assertTrue('access_token' in content)

        # check refresh token cannot be used twice
        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 401)
        content = json.loads(response.content.decode("utf-8"))
        self.assertTrue('invalid_grant' in content.values())
    def test_delete_view_post_actually_deletes(self):
        """
        Test that a POST on this view works if the token belongs to the logged-in user.
        """
        self.token = AccessToken.objects.create(user=self.foo_user, token='1234567890',
                                                application=self.application,
                                                expires=timezone.now() + datetime.timedelta(days=1),
                                                scope='read write')

        self.client.login(username="******", password="******")
        url = reverse("oauth2_provider:authorized-token-delete", kwargs={"pk": self.token.pk})
        response = self.client.post(url)
        self.assertFalse(AccessToken.objects.exists())
        self.assertRedirects(response, reverse('oauth2_provider:authorized-token-list'))
 def test_list_view_authorization_required(self):
     """
     Test that the view redirects to login page if user is not logged-in.
     """
     response = self.client.get(reverse('oauth2_provider:authorized-token-list'))
     self.assertEqual(response.status_code, 302)
     self.assertTrue('/accounts/login/?next=' in response['Location'])
    def test_password_resource_access_allowed(self):
        token_request_data = {
            'grant_type': 'password',
            'username': '******',
            'password': '******',
        }
        auth_headers = self.get_basic_auth_header(
            self.application.client_id, self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        content = json.loads(response.content.decode("utf-8"))
        access_token = content['access_token']

        # use token to access the resource
        auth_headers = {
            'HTTP_AUTHORIZATION': 'Bearer ' + access_token,
        }
        request = self.factory.get("/fake-resource", **auth_headers)
        request.user = self.test_user

        view = ResourceView.as_view()
        response = view(request)
        self.assertEqual(response, "This is a protected resource")
Esempio n. 12
0
    def test_resource_access_allowed(self):
        self.client.login(username="******", password="******")

        # retrieve a valid authorization code
        authcode_data = {
            'client_id': self.application.client_id,
            'state': 'random_state_string',
            'scope': 'read write',
            'redirect_uri': 'http://example.it',
            'response_type': 'token',
            'allow': True,
        }
        response = self.client.post(reverse('oauth2_provider:authorize'),
                                    data=authcode_data)
        # within implicit grant, access token is in the url fragment
        frag_dict = parse_qs(urlparse(response['Location']).fragment)
        access_token = frag_dict['access_token'].pop()

        # use token to access the resource
        auth_headers = {
            'HTTP_AUTHORIZATION': 'Bearer ' + access_token,
        }
        request = self.factory.get("/fake-resource", **auth_headers)
        request.user = self.test_user

        view = ResourceView.as_view()
        response = view(request)
        self.assertEqual(response, "This is a protected resource")
Esempio n. 13
0
    def test_basic_auth_grant_expired(self):
        """
        Request an access token using an expired grant token
        """
        self.client.login(username="******", password="******")
        g = Grant(application=self.application,
                  user=self.test_user,
                  code='BLAH',
                  expires=timezone.now(),
                  redirect_uri='',
                  scope='')
        g.save()

        token_request_data = {
            'grant_type': 'authorization_code',
            'code': 'BLAH',
            'redirect_uri': 'http://example.it'
        }
        auth_headers = get_basic_auth_header(self.application.client_id,
                                             self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 401)
Esempio n. 14
0
    def test_basic_auth(self):
        """
        Request an access token using basic authentication for client authentication
        """
        self.client.login(username="******", password="******")
        authorization_code = self.get_auth()

        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it'
        }
        auth_headers = get_basic_auth_header(self.application.client_id,
                                             self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 200)

        content = json.loads(response.content.decode("utf-8"))
        self.assertEqual(content['token_type'], "Bearer")
        self.assertEqual(content['scope'], "read write")
        self.assertEqual(content['expires_in'],
                         oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS)
    def test_client_credential_access_allowed(self):
        """
        Request an access token using Client Credential Flow
        """
        token_request_data = {
            'grant_type': 'client_credentials',
        }
        auth_headers = self.get_basic_auth_header(
            self.application.client_id, self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 200)

        content = json.loads(response.content.decode("utf-8"))
        access_token = content['access_token']

        # use token to access the resource
        auth_headers = {
            'HTTP_AUTHORIZATION': 'Bearer ' + access_token,
        }
        request = self.factory.get("/fake-resource", **auth_headers)
        request.user = self.test_user

        view = ResourceView.as_view()
        response = view(request)
        self.assertEqual(response, "This is a protected resource")
Esempio n. 16
0
 def test_pre_auth_approval_prompt(self):
     """
     TODO
     """
     tok = AccessToken.objects.create(user=self.test_user,
                                      token='1234567890',
                                      application=self.application,
                                      expires=timezone.now() +
                                      datetime.timedelta(days=1),
                                      scope='read write')
     self.client.login(username="******", password="******")
     query_string = urlencode({
         'client_id': self.application.client_id,
         'response_type': 'code',
         'state': 'random_state_string',
         'scope': 'read write',
         'redirect_uri': 'http://example.it',
         'approval_prompt': 'auto',
     })
     url = "{url}?{qs}".format(url=reverse('oauth2_provider:authorize'),
                               qs=query_string)
     response = self.client.get(url)
     self.assertEqual(response.status_code, 302)
     # user already authorized the application, but with different scopes: prompt them.
     tok.scope = 'read'
     tok.save()
     response = self.client.get(url)
     self.assertEqual(response.status_code, 200)
Esempio n. 17
0
    def test_pre_auth_valid_client(self):
        """
        Test response for a valid client_id with response_type: token
        """
        self.client.login(username="******", password="******")

        query_string = urlencode({
            'client_id': self.application.client_id,
            'response_type': 'token',
            'state': 'random_state_string',
            'scope': 'read write',
            'redirect_uri': 'http://example.it',
        })
        url = "{url}?{qs}".format(url=reverse('oauth2_provider:authorize'),
                                  qs=query_string)

        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

        # check form is in context and form params are valid
        self.assertIn("form", response.context)

        form = response.context["form"]
        self.assertEqual(form['redirect_uri'].value(), "http://example.it")
        self.assertEqual(form['state'].value(), "random_state_string")
        self.assertEqual(form['scope'].value(), "read write")
        self.assertEqual(form['client_id'].value(), self.application.client_id)
Esempio n. 18
0
    def test_public(self):
        """
        Request an access token using client_type: public
        """
        self.client.login(username="******", password="******")

        self.application.client_type = Application.CLIENT_PUBLIC
        self.application.save()
        authorization_code = self.get_auth()

        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it',
            'client_id': self.application.client_id
        }

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data)
        self.assertEqual(response.status_code, 200)

        content = json.loads(response.content.decode("utf-8"))
        self.assertEqual(content['token_type'], "Bearer")
        self.assertEqual(content['scope'], "read write")
        self.assertEqual(content['expires_in'],
                         oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS)
Esempio n. 19
0
    def test_multi_scope_valid(self):
        """
        Test access to a multi-scope protected resource with correct scopes provided
        """
        self.client.login(username="******", password="******")

        # retrieve a valid authorization code
        authcode_data = {
            'client_id': self.application.client_id,
            'state': 'random_state_string',
            'scope': 'scope1 scope2',
            'redirect_uri': 'http://example.it',
            'response_type': 'code',
            'allow': True,
        }
        response = self.client.post(reverse('oauth2_provider:authorize'),
                                    data=authcode_data)
        query_dict = parse_qs(urlparse(response['Location']).query)
        authorization_code = query_dict['code'].pop()

        # exchange authorization code for a valid access token
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it'
        }
        auth_headers = self.get_basic_auth_header(
            self.application.client_id, self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        content = json.loads(response.content.decode("utf-8"))
        access_token = content['access_token']

        # use token to access the resource
        auth_headers = {
            'HTTP_AUTHORIZATION': 'Bearer ' + access_token,
        }
        request = self.factory.get("/fake-resource", **auth_headers)
        request.user = self.test_user

        view = MultiScopeResourceView.as_view()
        response = view(request)
        self.assertEqual(response, "This is a protected resource")
    def test_empty_list_view(self):
        """
        Test that when you have no tokens, an appropriate message is shown
        """
        self.client.login(username="******", password="******")

        response = self.client.get(reverse('oauth2_provider:authorized-token-list'))
        self.assertEqual(response.status_code, 200)
        self.assertIn(b'There are no authorized tokens yet.', response.content)
    def test_delete_view_authorization_required(self):
        """
        Test that the view redirects to login page if user is not logged-in.
        """
        self.token = AccessToken.objects.create(user=self.foo_user, token='1234567890',
                                                application=self.application,
                                                expires=timezone.now() + datetime.timedelta(days=1),
                                                scope='read write')

        url = reverse("oauth2_provider:authorized-token-delete", kwargs={"pk": self.token.pk})
        response = self.client.get(url)
        self.assertEqual(response.status_code, 302)
        self.assertTrue('/accounts/login/?next=' in response['Location'])
    def test_delete_view_works(self):
        """
        Test that a GET on this view returns 200 if the token belongs to the logged-in user.
        """
        self.token = AccessToken.objects.create(user=self.foo_user, token='1234567890',
                                                application=self.application,
                                                expires=timezone.now() + datetime.timedelta(days=1),
                                                scope='read write')

        self.client.login(username="******", password="******")
        url = reverse("oauth2_provider:authorized-token-delete", kwargs={"pk": self.token.pk})
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
    def test_list_view_shows_correct_user_token(self):
        """
        Test that only currently logged-in user's tokens are shown
        """
        self.client.login(username="******", password="******")
        AccessToken.objects.create(user=self.foo_user, token='1234567890',
                                   application=self.application,
                                   expires=timezone.now() + datetime.timedelta(days=1),
                                   scope='read write')

        response = self.client.get(reverse('oauth2_provider:authorized-token-list'))
        self.assertEqual(response.status_code, 200)
        self.assertIn(b'There are no authorized tokens yet.', response.content)
    def test_delete_view_token_belongs_to_user(self):
        """
        Test that a 404 is returned when trying to GET this view with someone else's tokens.
        """
        self.token = AccessToken.objects.create(user=self.foo_user, token='1234567890',
                                                application=self.application,
                                                expires=timezone.now() + datetime.timedelta(days=1),
                                                scope='read write')

        self.client.login(username="******", password="******")
        url = reverse("oauth2_provider:authorized-token-delete", kwargs={"pk": self.token.pk})
        response = self.client.get(url)
        self.assertEqual(response.status_code, 404)
    def test_client_credential_user_is_none_on_access_token(self):
        token_request_data = {'grant_type': 'client_credentials'}
        auth_headers = self.get_basic_auth_header(
            self.application.client_id, self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 200)

        content = json.loads(response.content.decode("utf-8"))
        access_token = AccessToken.objects.get(token=content["access_token"])
        self.assertIsNone(access_token.user)
    def test_request_is_not_overwritten(self):
        self.client.login(username="******", password="******")
        query_string = urlencode({
            'client_id': self.application.client_id,
            'response_type': 'code',
            'state': 'random_state_string',
            'scope': 'read write',
            'redirect_uri': 'http://example.it',
        })
        url = "{url}?{qs}".format(url=reverse('oauth2_provider:authorize'), qs=query_string)

        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        assert 'request' not in response.context_data
    def test_client_credential_does_not_issue_refresh_token(self):
        token_request_data = {
            'grant_type': 'client_credentials',
        }
        auth_headers = self.get_basic_auth_header(
            self.application.client_id, self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data,
                                    **auth_headers)
        self.assertEqual(response.status_code, 200)

        content = json.loads(response.content.decode("utf-8"))
        self.assertNotIn("refresh_token", content)
    def test_pre_auth_invalid_client(self):
        """
        Test error for an invalid client_id with response_type: code
        """
        self.client.login(username="******", password="******")

        query_string = urlencode({
            'client_id': 'fakeclientid',
            'response_type': 'code',
        })
        url = "{url}?{qs}".format(url=reverse('oauth2_provider:authorize'), qs=query_string)

        response = self.client.get(url)
        self.assertEqual(response.status_code, 400)
    def test_pre_auth_wrong_response_type(self):
        """
        Test error when passing a wrong response_type in query string
        """
        self.client.login(username="******", password="******")

        query_string = urlencode({
            'client_id': self.application.client_id,
            'response_type': 'WRONG',
        })
        url = "{url}?{qs}".format(url=reverse('oauth2_provider:authorize'), qs=query_string)

        response = self.client.get(url)
        self.assertEqual(response.status_code, 302)
        self.assertIn("error=unsupported_response_type", response['Location'])
    def test_basic_auth_bad_granttype(self):
        """
        Request an access token using a bad grant_type string
        """
        self.client.login(username="******", password="******")

        token_request_data = {
            'grant_type': 'UNKNOWN',
            'code': 'BLAH',
            'redirect_uri': 'http://example.it'
        }
        auth_headers = self.get_basic_auth_header(self.application.client_id, self.application.client_secret)

        response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data, **auth_headers)
        self.assertEqual(response.status_code, 400)