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.org",
            "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. 2
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']
Esempio n. 3
0
    def _authorize_and_request_token(self, payload, application):
        response = self.client.post(reverse('oauth2_provider:authorize'),
                                    data=payload)
        self.assertEqual(response.status_code, 302)
        # now extract the authorization code and use it to request an access_token
        query_dict = parse_qs(urlparse(response['Location']).query)
        authorization_code = query_dict.pop('code')
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': 'http://example.it',
            'client_id': application.client_id,
        }

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

        response.status_code
        content = json.loads(response.content.decode("utf-8"))
        token = AccessToken.objects.get(token=content['access_token'])
        refresh_token = content['refresh_token']
        response_scopes = sorted(content['scope'].split())
        access_token_scopes = sorted(token.scope.split())

        return token, refresh_token, response.status_code, response_scopes, access_token_scopes
    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)
    def test_access_token_and_id_token_skip_authorization_completely(self):
        """
        If application.skip_authorization = True, should skip the authorization page.
        """
        self.client.login(username="******", password="******")
        self.application.skip_authorization = True
        self.application.save()

        query_string = urlencode({
            "client_id": self.application.client_id,
            "response_type": "id_token token",
            "state": "random_state_string",
            "nonce": "random_nonce_string",
            "scope": "openid",
            "redirect_uri": "http://example.org",
        })

        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("http://example.org#", response["Location"])
        self.assertIn("access_token=", response["Location"])
        self.assertIn("id_token=", response["Location"])
        self.assertIn("state=random_state_string", response["Location"])

        uri_query = urlparse(response["Location"]).fragment
        uri_query_params = dict(
            parse_qs(uri_query, keep_blank_values=True, strict_parsing=True))
        id_token = uri_query_params["id_token"][0]
        jwt_token = jwt.JWT(key=self.key, jwt=id_token)
        claims = json.loads(jwt_token.claims)
        self.assertIn("nonce", claims)
        self.assertIn("at_hash", claims)
    def test_access_token_and_id_token_post_auth_allow(self):
        """
        Test authorization code is given for an allowed request with response_type: token
        """
        self.client.login(username="******", password="******")

        form_data = {
            "client_id": self.application.client_id,
            "state": "random_state_string",
            "nonce": "random_nonce_string",
            "scope": "openid",
            "redirect_uri": "http://example.org",
            "response_type": "id_token token",
            "allow": True,
        }

        response = self.client.post(reverse("oauth2_provider:authorize"),
                                    data=form_data)
        self.assertEqual(response.status_code, 302)
        self.assertIn("http://example.org#", response["Location"])
        self.assertIn("access_token=", response["Location"])
        self.assertIn("id_token=", response["Location"])
        self.assertIn("state=random_state_string", response["Location"])

        uri_query = urlparse(response["Location"]).fragment
        uri_query_params = dict(
            parse_qs(uri_query, keep_blank_values=True, strict_parsing=True))
        id_token = uri_query_params["id_token"][0]
        jwt_token = jwt.JWT(key=self.key, jwt=id_token)
        claims = json.loads(jwt_token.claims)
        self.assertIn("nonce", claims)
        self.assertIn("at_hash", claims)
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_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. 9
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.org",
            "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.org"
        }
        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"))
        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. 11
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.org",
            "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.org"
        }
        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. 12
0
    def test_application_delete_after_auth(self):
        # Test that there are no errors with cascading deletes
        redirect_uri = 'http://localhost'
        # create a user
        self._create_user('anna', '123456')
        capability_a = self._create_capability('Capability A', [])
        capability_b = self._create_capability('Capability B', [])
        # create an application and add capabilities
        application = self._create_application(
            'an app',
            grant_type=Application.GRANT_AUTHORIZATION_CODE,
            client_type=Application.CLIENT_CONFIDENTIAL,
            redirect_uris=redirect_uri)
        application.scope.add(capability_a, capability_b)
        # user logs in
        self.client.login(username='******', password='******')
        # post the authorization form with only one scope selected
        payload = {
            'client_id': application.client_id,
            'response_type': 'code',
            'redirect_uri': redirect_uri,
            'scope': ['capability-a'],
            'expires_in': 86400,
            'allow': True,
        }
        response = self.client.post(reverse('oauth2_provider:authorize'),
                                    data=payload)
        self.client.logout()
        self.assertEqual(response.status_code, 302)
        # now extract the authorization code and use it to request an access_token
        query_dict = parse_qs(urlparse(response['Location']).query)
        authorization_code = query_dict.pop('code')
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': redirect_uri,
            'client_id': application.client_id,
            'client_secret': application.client_secret,
        }
        c = Client()
        response = c.post('/v1/o/token/', data=token_request_data)
        self.assertEqual(response.status_code, 200)
        # Now we have a token and refresh token
        tkn = response.json()['access_token']
        refresh_tkn = response.json()['refresh_token']

        # Test for cascading contraint errors.
        application_pk = application.pk
        application.delete()
        # Test related objects are deleted
        self.assertFalse(AccessToken.objects.filter(token=tkn).exists())
        self.assertTrue(ArchivedToken.objects.filter(token=tkn).exists())
        self.assertFalse(
            RefreshToken.objects.filter(token=refresh_tkn).exists())
        self.assertFalse(
            DataAccessGrant.objects.filter(
                application__pk=application_pk).exists())
        self.assertTrue(
            ArchivedDataAccessGrant.objects.filter(
                application__pk=application_pk).exists())
    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.org?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.org?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. 14
0
 def test_refresh_with_expired_token(self):
     redirect_uri = 'http://localhost'
     # create a user
     self._create_user('anna', '123456')
     capability_a = self._create_capability('Capability A', [])
     capability_b = self._create_capability('Capability B', [])
     # create an application and add capabilities
     application = self._create_application(
         'an app',
         grant_type=Application.GRANT_AUTHORIZATION_CODE,
         client_type=Application.CLIENT_CONFIDENTIAL,
         redirect_uris=redirect_uri)
     application.scope.add(capability_a, capability_b)
     # user logs in
     self.client.login(username='******', password='******')
     # post the authorization form with only one scope selected
     payload = {
         'client_id': application.client_id,
         'response_type': 'code',
         'redirect_uri': redirect_uri,
         'scope': ['capability-a'],
         'expires_in': 86400,
         'allow': True,
     }
     response = self.client.post(reverse('oauth2_provider:authorize'),
                                 data=payload)
     self.client.logout()
     self.assertEqual(response.status_code, 302)
     # now extract the authorization code and use it to request an access_token
     query_dict = parse_qs(urlparse(response['Location']).query)
     authorization_code = query_dict.pop('code')
     token_request_data = {
         'grant_type': 'authorization_code',
         'code': authorization_code,
         'redirect_uri': redirect_uri,
         'client_id': application.client_id,
         'client_secret': application.client_secret,
     }
     c = Client()
     response = c.post('/v1/o/token/', data=token_request_data)
     self.assertEqual(response.status_code, 200)
     # Now we have a token and refresh token
     tkn = response.json()['access_token']
     refresh_tkn = response.json()['refresh_token']
     at = AccessToken.objects.get(token=tkn)
     at.delete()
     refresh_request_data = {
         'grant_type': 'refresh_token',
         'refresh_token': refresh_tkn,
         'redirect_uri': redirect_uri,
         'client_id': application.client_id,
         'client_secret': application.client_secret,
     }
     response = self.client.post(reverse('oauth2_provider:token'),
                                 data=refresh_request_data)
     self.assertEqual(response.status_code, 401)
Esempio n. 15
0
    def _create_test_token(self, user, application):
        # user logs in
        self.client.force_login(user)
        # post the authorization form with only one scope selected
        payload = {
            'client_id': application.client_id,
            'response_type': 'code',
            'redirect_uri': application.redirect_uris,
            'scope': application.scopes().split(" "),
            'expires_in': 86400,
            'allow': True,
        }
        if application.authorization_grant_type == Application.GRANT_IMPLICIT:
            payload['response_type'] = 'token'
        response = self.client.post('/v1/o/authorize/', data=payload)
        self.client.logout()
        if response.status_code != 302:
            raise Exception(response.context_data)
        self.assertEqual(response.status_code, 302)
        # now extract the authorization code and use it to request an access_token
        if application.authorization_grant_type == Application.GRANT_IMPLICIT:
            fragment = parse_qs(urlparse(response['Location']).fragment)
            tkn = fragment.pop('access_token')[0]
        else:
            query_dict = parse_qs(urlparse(response['Location']).query)
            authorization_code = query_dict.pop('code')
            token_request_data = {
                'grant_type': 'authorization_code',
                'code': authorization_code,
                'redirect_uri': application.redirect_uris,
                'client_id': application.client_id,
                'client_secret': application.client_secret,
            }

            response = self.client.post('/v1/o/token/',
                                        data=token_request_data)
            self.assertEqual(response.status_code, 200)
            # Now we have a token and refresh token
            tkn = response.json()['access_token']

        t = AccessToken.objects.get(token=tkn)
        return t
Esempio n. 16
0
    def test_post_with_valid_non_standard_scheme(self):
        redirect_uri = 'com.custom.bluebutton://example.it'
        # create a user
        self._create_user('anna', '123456')
        capability_a = self._create_capability('Capability A', [])
        capability_b = self._create_capability('Capability B', [])
        # create an application and add capabilities
        application = self._create_application(
            'an app',
            grant_type=Application.GRANT_AUTHORIZATION_CODE,
            redirect_uris=redirect_uri)
        application.scope.add(capability_a, capability_b)

        # user logs in
        self.client.login(username='******', password='******')

        code_challenge = "sZrievZsrYqxdnu2NVD603EiYBM18CuzZpwB-pOSZjo"

        payload = {
            'client_id': application.client_id,
            'response_type': 'code',
            'redirect_uri': redirect_uri,
            'code_challenge': code_challenge,
            'code_challenge_method': 'S256',
        }
        response = self.client.get('/v1/o/authorize', data=payload)
        # post the authorization form with only one scope selected
        payload = {
            'client_id': application.client_id,
            'response_type': 'code',
            'redirect_uri': redirect_uri,
            'scope': ['capability-a'],
            'expires_in': 86400,
            'allow': True,
            'code_challenge': code_challenge,
            'code_challenge_method': 'S256',
        }
        response = self.client.post(response['Location'], data=payload)

        self.assertEqual(response.status_code, 302)
        # now extract the authorization code and use it to request an access_token
        query_dict = parse_qs(urlparse(response['Location']).query)
        authorization_code = query_dict.pop('code')
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': redirect_uri,
            'client_id': application.client_id,
            'code_verifier':
            'test123456789123456789123456789123456789123456789',
        }
        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data)
        self.assertEqual(response.status_code, 200)
Esempio n. 17
0
    def test_creation_on_approval(self):
        redirect_uri = 'http://localhost'
        # create a user
        user = self._create_user('anna', '123456')
        capability_a = self._create_capability('Capability A', [])
        capability_b = self._create_capability('Capability B', [])
        # create an application and add capabilities
        application = self._create_application(
            'an app',
            grant_type=Application.GRANT_AUTHORIZATION_CODE,
            redirect_uris=redirect_uri)
        application.scope.add(capability_a, capability_b)

        # user logs in
        self.client.login(username='******', password='******')

        payload = {
            'client_id': application.client_id,
            'response_type': 'code',
            'redirect_uri': redirect_uri,
        }
        response = self.client.get('/v1/o/authorize', data=payload)
        # post the authorization form with only one scope selected
        payload = {
            'client_id': application.client_id,
            'response_type': 'code',
            'redirect_uri': redirect_uri,
            'scope': ['capability-a'],
            'expires_in': 86400,
            'allow': True,
        }
        response = self.client.post(response['Location'], data=payload)

        self.assertEqual(response.status_code, 302)
        # now extract the authorization code and use it to request an access_token
        query_dict = parse_qs(urlparse(response['Location']).query)
        authorization_code = query_dict.pop('code')
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': redirect_uri,
            'client_id': application.client_id,
        }
        response = self.client.post(reverse('oauth2_provider:token'),
                                    data=token_request_data)
        self.assertEqual(response.status_code, 200)

        # errors if DNE or more than one is found
        DataAccessGrant.objects.get(beneficiary=user.id,
                                    application=application.id)
 def _authorize_and_request_token(self, payload, application):
     response = self.client.post(reverse('oauth2_provider:authorize'),
                                 data=payload)
     self.assertEqual(response.status_code, 302)
     # now extract the authorization code and use it to request an access_token
     query_dict = parse_qs(urlparse(response['Location']).query)
     authorization_code = query_dict.pop('code')
     token_request_data = {
         'grant_type': 'authorization_code',
         'code': authorization_code,
         'redirect_uri': 'http://example.it',
         'client_id': application.client_id,
     }
     return self.client.post(reverse('oauth2_provider:token'),
                             data=token_request_data)
    def get_auth(self):
        """
        Helper method to 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': 'code',
            'allow': True,
        }

        response = self.client.post(reverse('oauth2_provider:authorize'), data=authcode_data)
        query_dict = parse_qs(urlparse(response['Location']).query)
        return query_dict['code'].pop()
    def get_auth(self):
        """
        Helper method to retrieve a valid authorization code
        """
        authcode_data = {
            "client_id": self.application.client_id,
            "state": "random_state_string",
            "scope": "read write",
            "redirect_uri": "http://example.org",
            "response_type": "code",
            "allow": True,
        }

        response = self.client.post(reverse("oauth2_provider:authorize"),
                                    data=authcode_data)
        query_dict = parse_qs(urlparse(response["Location"]).query)
        return query_dict["code"].pop()
 def test_post_with_restricted_scopes_issues_token_with_same_scopes(self):
     """
     Test that when user unchecks some of the scopes the token is issued
     with the checked scopes only.
     """
     # create a user
     self._create_user('anna', '123456')
     # create a couple of capabilities
     capability_a = self._create_capability('Capability A', [])
     capability_b = self._create_capability('Capability B', [])
     # create an application and add capabilities
     application = self._create_application(
         'an app',
         grant_type=Application.GRANT_AUTHORIZATION_CODE,
         redirect_uris='http://example.it')
     application.scope.add(capability_a, capability_b)
     # user logs in
     self.client.login(username='******', password='******')
     # post the authorization form with only one scope selected
     payload = {
         'client_id': application.client_id,
         'response_type': 'code',
         'redirect_uri': 'http://example.it',
         'scope': ['capability-a'],
         'expires_in': 86400,
         'allow': True,
     }
     response = self.client.post(reverse('oauth2_provider:authorize'),
                                 data=payload)
     self.assertEqual(response.status_code, 302)
     # now extract the authorization code and use it to request an access_token
     query_dict = parse_qs(urlparse(response['Location']).query)
     authorization_code = query_dict.pop('code')
     token_request_data = {
         'grant_type': 'authorization_code',
         'code': authorization_code,
         'redirect_uri': 'http://example.it',
         'client_id': 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"))
     # and here we test that only the capability-a scope has been issued
     self.assertEqual(content['scope'], "capability-a")
Esempio n. 22
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.org",
            "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.org"
        }
        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"]

        # 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")
Esempio n. 23
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_code_exchange_succeed_when_redirect_uri_match_with_multiple_query_params(
            self):
        """
        Tests code exchange succeed when redirect uri matches the one used for code request
        """
        self.client.login(username="******", password="******")
        self.application.redirect_uris = "http://localhost http://example.com?foo=bar"
        self.application.save()

        # retrieve a valid authorization code
        authcode_data = {
            "client_id": self.application.client_id,
            "state": "random_state_string",
            "scope": "read write",
            "redirect_uri": "http://example.com?bar=baz&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.com?bar=baz&foo=bar"
        }
        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_post_with_restricted_scopes_issues_token_with_same_scopes(self):
     """
     Test that when user unchecks some of the scopes the token is issued
     with the checked scopes only.
     """
     # create a user
     self._create_user('anna', '123456')
     # create a couple of capabilities
     capability_a = self._create_capability('Capability A', [])
     capability_b = self._create_capability('Capability B', [])
     # create an application and add capabilities
     application = self._create_application(
         'an app', grant_type=Application.GRANT_AUTHORIZATION_CODE,
         redirect_uris='http://example.it')
     application.scope.add(capability_a, capability_b)
     # user logs in
     self.client.login(username='******', password='******')
     # post the authorization form with only one scope selected
     payload = {
         'client_id': application.client_id,
         'response_type': 'code',
         'redirect_uri': 'http://example.it',
         'scope': ['capability-a'],
         'expires_in': 86400,
         'allow': True,
     }
     response = self.client.post(reverse('oauth2_provider:authorize'), data=payload)
     self.assertEqual(response.status_code, 302)
     # now extract the authorization code and use it to request an access_token
     query_dict = parse_qs(urlparse(response['Location']).query)
     authorization_code = query_dict.pop('code')
     token_request_data = {
         'grant_type': 'authorization_code',
         'code': authorization_code,
         'redirect_uri': 'http://example.it',
         'client_id': 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"))
     # and here we test that only the capability-a scope has been issued
     self.assertEqual(content['scope'], "capability-a")
Esempio n. 26
0
    def test_scopes_saved_in_grant(self):
        """
        Test scopes are properly saved in grant
        """
        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.org",
            "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()

        grant = Grant.objects.get(code=authorization_code)
        self.assertEqual(grant.scope, "scope1 scope2")
Esempio n. 27
0
    def test_scopes_saved_in_grant(self):
        """
        Test scopes are properly saved in grant
        """
        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()

        grant = Grant.objects.get(code=authorization_code)
        self.assertEqual(grant.scope, "scope1 scope2")
Esempio n. 28
0
    def test_post_with_valid_non_standard_scheme_granttype_authcode_clienttype_confidential(self):
        # Test with application setup as grant_type=authorization_code and client_type=confidential
        redirect_uri = 'com.custom.bluebutton://example.it'
        # create a user
        self._create_user('anna', '123456')
        capability_a = self._create_capability('Capability A', [])
        capability_b = self._create_capability('Capability B', [])
        # create an application and add capabilities
        application = self._create_application(
            'an app',
            grant_type=Application.GRANT_AUTHORIZATION_CODE,
            client_type=Application.CLIENT_CONFIDENTIAL,
            redirect_uris=redirect_uri)
        application.scope.add(capability_a, capability_b)

        # user logs in
        self.client.login(username='******', password='******')

        code_challenge = "sZrievZsrYqxdnu2NVD603EiYBM18CuzZpwB-pOSZjo"

        payload = {
            'client_id': application.client_id,
            'response_type': 'code',
            'redirect_uri': redirect_uri,
            'code_challenge': code_challenge,
            'code_challenge_method': 'S256',
        }
        response = self.client.get('/v1/o/authorize', data=payload)
        # post the authorization form with only one scope selected
        payload = {
            'client_id': application.client_id,
            'response_type': 'code',
            'redirect_uri': redirect_uri,
            'scope': ['capability-a'],
            'expires_in': 86400,
            'allow': True,
            'code_challenge': code_challenge,
            'code_challenge_method': 'S256',
        }
        response = self.client.post(response['Location'], data=payload)

        self.assertEqual(response.status_code, 302)
        # now extract the authorization code and use it to request an access_token
        query_dict = parse_qs(urlparse(response['Location']).query)
        authorization_code = query_dict.pop('code')
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': redirect_uri,
            'client_id': application.client_id,
        }
        # Test that request is unauthorized WITH OUT the client_secret.
        token_request_data.update({'code_verifier': 'test123456789123456789123456789123456789123456789'})
        response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data)
        self.assertEqual(response.status_code, 401)

        # Setup application's client_secret
        token_request_data.update({'client_secret': application.client_secret})

        # Test that using a BAD code_verifier has a bad request response
        token_request_data.update({'code_verifier': 'test1234567bad9verifier23456789123456789123456789'})
        response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data)
        self.assertEqual(response.status_code, 400)

        # Test that request is successful WITH the client_secret and GOOD code_verifier
        token_request_data.update({'code_verifier': 'test123456789123456789123456789123456789123456789'})
        response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data)
        self.assertEqual(response.status_code, 200)

        # Test 2nd access token request is unauthorized
        response = self.client.post(reverse('oauth2_provider:token'), data=token_request_data)
        self.assertEqual(response.status_code, 401)
Esempio n. 29
0
    def test_introspect_token_on_inactive_app(self):
        '''
        BB2-149:
        adapted from token auth test but test token introspect on a inactive app,
        403 customized permission denied message expected.
        '''
        redirect_uri = 'http://localhost'
        # create a user
        self._create_user('anna', '123456')
        capability_a = self._create_capability('Capability A', [])
        capability_b = self._create_capability('Capability B', [])
        capability_introspect = self._create_capability('introspection', [])
        # create an application and add capabilities
        application = self._create_application(
            'an app',
            grant_type=Application.GRANT_AUTHORIZATION_CODE,
            client_type=Application.CLIENT_CONFIDENTIAL,
            redirect_uris=redirect_uri)
        application.scope.add(capability_a, capability_b, capability_introspect)
        # user logs in
        self.client.login(username='******', password='******')
        # post the authorization form with only one scope selected
        payload = {
            'client_id': application.client_id,
            'response_type': 'code',
            'redirect_uri': redirect_uri,
            'scope': ['capability-a', 'capability-b', 'introspection'],
            'expires_in': 86400,
            'allow': True,
        }
        response = self.client.post(reverse('oauth2_provider:authorize'), data=payload)
        self.client.logout()
        self.assertEqual(response.status_code, 302)
        # now extract the authorization code and use it to request an access_token
        query_dict = parse_qs(urlparse(response['Location']).query)
        authorization_code = query_dict.pop('code')
        token_request_data = {
            'grant_type': 'authorization_code',
            'code': authorization_code,
            'redirect_uri': redirect_uri,
            'client_id': application.client_id,
            'client_secret': application.client_secret,
        }
        c = Client()
        response = c.post('/v1/o/token/', data=token_request_data)
        self.assertEqual(response.status_code, 200)
        # Now we have a token and refresh token
        tkn = response.json()['access_token']
        introspect_request_data = {
            'token': tkn,
            'client_id': application.client_id,
            'client_secret': application.client_secret,
        }

        auth_headers = {'Authorization': 'Bearer %s' % tkn}

        # set app to inactive before introspect
        application.active = False
        application.save()

        msg_expected = settings.APPLICATION_TEMPORARILY_INACTIVE.format("an app")
        response = c.post('/v1/o/introspect/', data=introspect_request_data, **auth_headers)
        # asssert 403 and content json message
        self.assertEqual(response.status_code, 403)
        content = json.loads(response.content.decode("utf-8"))
        self.assertEqual(content['detail'], msg_expected)

        # revert app to active in case not to impact other tests
        application.active = True
        application.save()