Beispiel #1
0
 def setUp(self):
     super(TestOAuthDispatchAPI, self).setUp()
     self.adapter = DOTAdapter()
     self.user = UserFactory()
     self.client = self.adapter.create_public_client(
         name='public app',
         user=self.user,
         redirect_uri=DUMMY_REDIRECT_URL,
         client_id='public-client-id',
     )
Beispiel #2
0
def _create_and_set_jwt_cookies(response, request, cookie_settings, user=None, refresh_token=None):
    """ Sets a cookie containing a JWT on the response. """

    if _are_jwt_cookies_disabled():
        return

    # For security reasons, the JWT that is embedded inside the cookie expires
    # much sooner than the cookie itself, per the following setting.
    expires_in = settings.JWT_AUTH['JWT_IN_COOKIE_EXPIRATION']

    oauth_application = _get_login_oauth_client()
    if refresh_token:
        access_token = refresh_dot_access_token(
            request, oauth_application.client_id, refresh_token, expires_in=expires_in,
        )
    else:
        access_token = create_dot_access_token(
            request, user, oauth_application, expires_in=expires_in, scopes=['email', 'profile'],
        )
    jwt = create_jwt_from_token(access_token, DOTAdapter(), use_asymmetric_key=True)
    jwt_header_and_payload, jwt_signature = _parse_jwt(jwt)
    _set_jwt_cookies(
        response,
        cookie_settings,
        jwt_header_and_payload,
        jwt_signature,
        access_token['refresh_token'],
    )
Beispiel #3
0
 def test_dot_create_jwt_for_token(self, client_restricted):
     jwt_token = self._create_jwt_for_token(
         DOTAdapter(),
         use_asymmetric_key=None,
         client_restricted=client_restricted,
     )
     self._assert_jwt_is_valid(jwt_token, should_be_asymmetric_key=client_restricted)
 def test_dot_create_jwt_for_token(self, scopes_enforced, client_restricted):
     with ENFORCE_JWT_SCOPES.override(scopes_enforced):
         jwt_token = self._create_jwt_for_token(
             DOTAdapter(),
             use_asymmetric_key=None,
             client_restricted=client_restricted,
         )
         self._assert_jwt_is_valid(jwt_token, should_be_asymmetric_key=scopes_enforced and client_restricted)
Beispiel #5
0
class TestOAuthDispatchAPI(TestCase):
    """ Tests for oauth_dispatch's api.py module. """
    def setUp(self):
        super(TestOAuthDispatchAPI, self).setUp()
        self.adapter = DOTAdapter()
        self.user = UserFactory()
        self.client = self.adapter.create_public_client(
            name='public app',
            user=self.user,
            redirect_uri=DUMMY_REDIRECT_URL,
            client_id='public-client-id',
        )

    def _assert_stored_token(self, stored_token_value, expected_token_user,
                             expected_client):
        stored_access_token = AccessToken.objects.get(token=stored_token_value)
        self.assertEqual(stored_access_token.user.id, expected_token_user.id)
        self.assertEqual(stored_access_token.application.client_id,
                         expected_client.client_id)
        self.assertEqual(stored_access_token.application.user.id,
                         expected_client.user.id)

    def test_create_token_success(self):
        token = api.create_dot_access_token(HttpRequest(), self.user,
                                            self.client)
        self.assertTrue(token['access_token'])
        self.assertTrue(token['refresh_token'])
        self.assertDictContainsSubset(
            {
                u'token_type': u'Bearer',
                u'expires_in': EXPECTED_DEFAULT_EXPIRES_IN,
                u'scope': u'',
            },
            token,
        )
        self._assert_stored_token(token['access_token'], self.user,
                                  self.client)

    def test_create_token_another_user(self):
        another_user = UserFactory()
        token = api.create_dot_access_token(HttpRequest(), another_user,
                                            self.client)
        self._assert_stored_token(token['access_token'], another_user,
                                  self.client)

    def test_create_token_overrides(self):
        expires_in = 4800
        token = api.create_dot_access_token(
            HttpRequest(),
            self.user,
            self.client,
            expires_in=expires_in,
            scopes=['profile'],
        )
        self.assertDictContainsSubset({u'scope': u'profile'}, token)
        self.assertDictContainsSubset({u'expires_in': expires_in}, token)
Beispiel #6
0
def _create_jwt(request, user, expires_in):
    """
    Creates and returns a jwt for the given user with the given expires_in value.
    """
    oauth_application = _get_login_oauth_client()
    access_token = create_dot_access_token(
        # Note: Scopes for JWT cookies do not require additional permissions
        request, user, oauth_application, expires_in=expires_in, scopes=['user_id', 'email', 'profile'],
    )
    return create_jwt_from_token(access_token, DOTAdapter(), use_asymmetric_key=True)
Beispiel #7
0
 def setUp(self):
     super(TestOAuthDispatchAPI, self).setUp()
     self.adapter = DOTAdapter()
     self.user = UserFactory()
     self.client = self.adapter.create_public_client(
         name='public app',
         user=self.user,
         redirect_uri=DUMMY_REDIRECT_URL,
         client_id='public-client-id',
     )
Beispiel #8
0
def _create_and_set_jwt_cookies(response,
                                request,
                                cookie_settings,
                                user=None,
                                refresh_token=None):
    """ Sets a cookie containing a JWT on the response. """

    # Skip setting JWT cookies for most unit tests, since it raises errors when
    # a login oauth client cannot be found in the database in ``_get_login_oauth_client``.
    # This solution is not ideal, but see https://github.com/edx/edx-platform/pull/19180#issue-226706355
    # for a discussion of alternative solutions that did not work or were halted.
    if settings.FEATURES.get('DISABLE_SET_JWT_COOKIES_FOR_TESTS', False):
        return

    # For Ironwood, we don't set JWK settings by default.  Make sure we don't fail trying
    # to use empty settings.  This means by default, micro-frontends won't work, but Ironwood
    # has none.  Also, OAuth scopes won't work, but that is still a new and specialized feature.
    # Installations that need them can create JWKs and add them to the settings.
    private_signing_jwk = settings.JWT_AUTH['JWT_PRIVATE_SIGNING_JWK']
    if private_signing_jwk == "None" or not private_signing_jwk:
        return

    # For security reasons, the JWT that is embedded inside the cookie expires
    # much sooner than the cookie itself, per the following setting.
    expires_in = settings.JWT_AUTH['JWT_IN_COOKIE_EXPIRATION']

    oauth_application = _get_login_oauth_client()
    if refresh_token:
        access_token = refresh_dot_access_token(
            request,
            oauth_application.client_id,
            refresh_token,
            expires_in=expires_in,
        )
    else:
        access_token = create_dot_access_token(
            request,
            user,
            oauth_application,
            expires_in=expires_in,
            scopes=['email', 'profile'],
        )
    jwt = create_jwt_from_token(access_token,
                                DOTAdapter(),
                                use_asymmetric_key=True)
    jwt_header_and_payload, jwt_signature = _parse_jwt(jwt)
    _set_jwt_cookies(
        response,
        cookie_settings,
        jwt_header_and_payload,
        jwt_signature,
        access_token['refresh_token'],
    )
Beispiel #9
0
def _create_and_set_jwt_cookies(response,
                                request,
                                cookie_settings,
                                user=None,
                                refresh_token=None):
    """ Sets a cookie containing a JWT on the response. """

    # Skip setting JWT cookies for most unit tests, since it raises errors when
    # a login oauth client cannot be found in the database in ``_get_login_oauth_client``.
    # This solution is not ideal, but see https://github.com/edx/edx-platform/pull/19180#issue-226706355
    # for a discussion of alternative solutions that did not work or were halted.
    if settings.FEATURES.get('DISABLE_SET_JWT_COOKIES_FOR_TESTS', False):
        return

    # For security reasons, the JWT that is embedded inside the cookie expires
    # much sooner than the cookie itself, per the following setting.
    expires_in = settings.JWT_AUTH['JWT_IN_COOKIE_EXPIRATION']

    oauth_application = _get_login_oauth_client()
    if refresh_token:
        access_token = refresh_dot_access_token(
            request,
            oauth_application.client_id,
            refresh_token,
            expires_in=expires_in,
        )
    else:
        access_token = create_dot_access_token(
            # Note: Scopes for JWT cookies do not require additional permissions
            request,
            user,
            oauth_application,
            expires_in=expires_in,
            scopes=['user_id', 'email', 'profile'],
        )
    jwt = create_jwt_from_token(access_token,
                                DOTAdapter(),
                                use_asymmetric_key=True)
    jwt_header_and_payload, jwt_signature = _parse_jwt(jwt)
    _set_jwt_cookies(
        response,
        cookie_settings,
        jwt_header_and_payload,
        jwt_signature,
        access_token['refresh_token'],
    )
Beispiel #10
0
class TestOAuthDispatchAPI(TestCase):
    """ Tests for oauth_dispatch's api.py module. """
    def setUp(self):
        super(TestOAuthDispatchAPI, self).setUp()
        self.adapter = DOTAdapter()
        self.user = UserFactory()
        self.client = self.adapter.create_public_client(
            name='public app',
            user=self.user,
            redirect_uri=DUMMY_REDIRECT_URL,
            client_id='public-client-id',
        )

    def _assert_stored_token(self, stored_token_value, expected_token_user, expected_client):
        stored_access_token = AccessToken.objects.get(token=stored_token_value)
        self.assertEqual(stored_access_token.user.id, expected_token_user.id)
        self.assertEqual(stored_access_token.application.client_id, expected_client.client_id)
        self.assertEqual(stored_access_token.application.user.id, expected_client.user.id)

    def test_create_token_success(self):
        token = api.create_dot_access_token(HttpRequest(), self.user, self.client)
        self.assertTrue(token['access_token'])
        self.assertTrue(token['refresh_token'])
        self.assertDictContainsSubset(
            {
                u'token_type': u'Bearer',
                u'expires_in': EXPECTED_DEFAULT_EXPIRES_IN,
                u'scope': u'',
            },
            token,
        )
        self._assert_stored_token(token['access_token'], self.user, self.client)

    def test_create_token_another_user(self):
        another_user = UserFactory()
        token = api.create_dot_access_token(HttpRequest(), another_user, self.client)
        self._assert_stored_token(token['access_token'], another_user, self.client)

    def test_create_token_overrides(self):
        expires_in = 4800
        token = api.create_dot_access_token(
            HttpRequest(), self.user, self.client, expires_in=expires_in, scopes=['profile'],
        )
        self.assertDictContainsSubset({u'scope': u'profile'}, token)
        self.assertDictContainsSubset({u'expires_in': expires_in}, token)
Beispiel #11
0
def _create_and_set_jwt_cookies(response,
                                request,
                                user=None,
                                refresh_token=None):
    """ Sets a cookie containing a JWT on the response. """
    if not JWT_COOKIES_FLAG.is_enabled():
        return

    # JWT cookies expire at the same time as other login-related cookies
    # so that cookie-based login determination remains consistent.
    cookie_settings = standard_cookie_settings(request)

    # For security reasons, the JWT that is embedded inside the cookie expires
    # much sooner than the cookie itself, per the following setting.
    expires_in = settings.JWT_AUTH['JWT_IN_COOKIE_EXPIRATION']

    oauth_application = _get_login_oauth_client()
    if refresh_token:
        access_token = refresh_dot_access_token(
            request,
            oauth_application.client_id,
            refresh_token,
            expires_in=expires_in,
        )
    else:
        access_token = create_dot_access_token(
            request,
            user,
            oauth_application,
            expires_in=expires_in,
        )
    jwt = create_jwt_from_token(access_token,
                                DOTAdapter(),
                                use_asymmetric_key=True)
    jwt_header_and_payload, jwt_signature = _parse_jwt(jwt)
    _set_jwt_cookies(
        response,
        cookie_settings,
        jwt_header_and_payload,
        jwt_signature,
        access_token['refresh_token'],
    )
Beispiel #12
0
def _create_and_set_jwt_cookies(response,
                                request,
                                user=None,
                                refresh_token=None):
    """ Sets a cookie containing a JWT on the response. """
    if not JWT_COOKIES_FLAG.is_enabled():
        return

    # TODO (ARCH-246) Need to fix configuration of token expiration settings.
    cookie_settings = standard_cookie_settings(request)
    _set_jwt_expiration(cookie_settings)
    expires_in = cookie_settings['max_age']

    oauth_application = _get_login_oauth_client()
    if refresh_token:
        access_token = refresh_dot_access_token(
            request,
            oauth_application.client_id,
            refresh_token,
            expires_in=expires_in,
        )
    else:
        access_token = create_dot_access_token(
            request,
            user,
            oauth_application,
            expires_in=expires_in,
        )
    jwt = create_jwt_from_token(access_token,
                                DOTAdapter(),
                                use_asymmetric_key=True)
    jwt_header_and_payload, jwt_signature = _parse_jwt(jwt)
    _set_jwt_cookies(
        response,
        cookie_settings,
        jwt_header_and_payload,
        jwt_signature,
        access_token['refresh_token'],
    )
Beispiel #13
0
 def test_dot_create_jwt_for_token_with_asymmetric(self):
     jwt_token = self._create_jwt_for_token(DOTAdapter(),
                                            use_asymmetric_key=True)
     self._assert_jwt_is_valid(jwt_token, should_be_asymmetric_key=True)
Beispiel #14
0
 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)
Beispiel #15
0
class TestOAuthDispatchAPI(TestCase):
    """ Tests for oauth_dispatch's api.py module. """
    def setUp(self):
        super(TestOAuthDispatchAPI, self).setUp()
        self.adapter = DOTAdapter()
        self.user = UserFactory()
        self.client = self.adapter.create_public_client(
            name='public app',
            user=self.user,
            redirect_uri=DUMMY_REDIRECT_URL,
            client_id='public-client-id',
        )

    def _assert_stored_token(self, stored_token_value, expected_token_user,
                             expected_client):
        stored_access_token = AccessToken.objects.get(token=stored_token_value)
        self.assertEqual(stored_access_token.user.id, expected_token_user.id)
        self.assertEqual(stored_access_token.application.client_id,
                         expected_client.client_id)
        self.assertEqual(stored_access_token.application.user.id,
                         expected_client.user.id)

    def test_create_token_success(self):
        token = api.create_dot_access_token(HttpRequest(), self.user,
                                            self.client)
        self.assertTrue(token['access_token'])
        self.assertTrue(token['refresh_token'])
        self.assertDictContainsSubset(
            {
                u'token_type': u'Bearer',
                u'expires_in': EXPECTED_DEFAULT_EXPIRES_IN,
                u'scope': u'default',
            },
            token,
        )
        self._assert_stored_token(token['access_token'], self.user,
                                  self.client)

    def test_create_token_another_user(self):
        another_user = UserFactory()
        token = api.create_dot_access_token(HttpRequest(), another_user,
                                            self.client)
        self._assert_stored_token(token['access_token'], another_user,
                                  self.client)

    def test_create_token_overrides(self):
        expires_in = 4800
        token = api.create_dot_access_token(HttpRequest(),
                                            self.user,
                                            self.client,
                                            expires_in=expires_in,
                                            scope=2)
        self.assertDictContainsSubset({u'scope': u'profile'}, token)
        self.assertDictContainsSubset({u'expires_in': expires_in}, token)

    def test_refresh_token_success(self):
        old_token = api.create_dot_access_token(HttpRequest(), self.user,
                                                self.client)
        new_token = api.refresh_dot_access_token(HttpRequest(),
                                                 self.client.client_id,
                                                 old_token['refresh_token'])
        self.assertDictContainsSubset(
            {
                u'token_type': u'Bearer',
                u'expires_in': EXPECTED_DEFAULT_EXPIRES_IN,
                u'scope': u'default',
            },
            new_token,
        )

        # verify new tokens are generated
        self.assertNotEqual(old_token['access_token'],
                            new_token['access_token'])
        self.assertNotEqual(old_token['refresh_token'],
                            new_token['refresh_token'])

        # verify old token is replaced by the new token
        with self.assertRaises(AccessToken.DoesNotExist):
            self._assert_stored_token(old_token['access_token'], self.user,
                                      self.client)
        self._assert_stored_token(new_token['access_token'], self.user,
                                  self.client)

    def test_refresh_token_invalid_client(self):
        token = api.create_dot_access_token(HttpRequest(), self.user,
                                            self.client)
        with self.assertRaises(api.OAuth2Error) as error:
            api.refresh_dot_access_token(
                HttpRequest(),
                'invalid_client_id',
                token['refresh_token'],
            )
        self.assertIn('invalid_client', error.exception.description)

    def test_refresh_token_invalid_token(self):
        api.create_dot_access_token(HttpRequest(), self.user, self.client)
        with self.assertRaises(api.OAuth2Error) as error:
            api.refresh_dot_access_token(
                HttpRequest(),
                self.client.client_id,
                'invalid_refresh_token',
            )
        self.assertIn('invalid_grant', error.exception.description)
Beispiel #16
0
class TestOAuthDispatchAPI(TestCase):
    """ Tests for oauth_dispatch's api.py module. """
    def setUp(self):
        super(TestOAuthDispatchAPI, self).setUp()
        self.adapter = DOTAdapter()
        self.user = UserFactory()
        self.client = self.adapter.create_public_client(
            name='public app',
            user=self.user,
            redirect_uri=DUMMY_REDIRECT_URL,
            client_id='public-client-id',
        )

    def _assert_stored_token(self, stored_token_value, expected_token_user, expected_client):
        stored_access_token = AccessToken.objects.get(token=stored_token_value)
        self.assertEqual(stored_access_token.user.id, expected_token_user.id)
        self.assertEqual(stored_access_token.application.client_id, expected_client.client_id)
        self.assertEqual(stored_access_token.application.user.id, expected_client.user.id)

    def test_create_token_success(self):
        token = api.create_dot_access_token(HttpRequest(), self.user, self.client)
        self.assertTrue(token['access_token'])
        self.assertTrue(token['refresh_token'])
        self.assertDictContainsSubset(
            {
                u'token_type': u'Bearer',
                u'expires_in': EXPECTED_DEFAULT_EXPIRES_IN,
                u'scope': u'',
            },
            token,
        )
        self._assert_stored_token(token['access_token'], self.user, self.client)

    def test_create_token_another_user(self):
        another_user = UserFactory()
        token = api.create_dot_access_token(HttpRequest(), another_user, self.client)
        self._assert_stored_token(token['access_token'], another_user, self.client)

    def test_create_token_overrides(self):
        expires_in = 4800
        token = api.create_dot_access_token(
            HttpRequest(), self.user, self.client, expires_in=expires_in, scopes=['profile'],
        )
        self.assertDictContainsSubset({u'scope': u'profile'}, token)
        self.assertDictContainsSubset({u'expires_in': expires_in}, token)

    def test_refresh_token_success(self):
        old_token = api.create_dot_access_token(HttpRequest(), self.user, self.client)
        new_token = api.refresh_dot_access_token(HttpRequest(), self.client.client_id, old_token['refresh_token'])
        self.assertDictContainsSubset(
            {
                u'token_type': u'Bearer',
                u'expires_in': EXPECTED_DEFAULT_EXPIRES_IN,
                u'scope': u'',
            },
            new_token,
        )

        # verify new tokens are generated
        self.assertNotEqual(old_token['access_token'], new_token['access_token'])
        self.assertNotEqual(old_token['refresh_token'], new_token['refresh_token'])

        # verify old token is replaced by the new token
        with self.assertRaises(AccessToken.DoesNotExist):
            self._assert_stored_token(old_token['access_token'], self.user, self.client)
        self._assert_stored_token(new_token['access_token'], self.user, self.client)

    def test_refresh_token_invalid_client(self):
        token = api.create_dot_access_token(HttpRequest(), self.user, self.client)
        with self.assertRaises(api.OAuth2Error) as error:
            api.refresh_dot_access_token(
                HttpRequest(), 'invalid_client_id', token['refresh_token'],
            )
        self.assertIn('invalid_client', error.exception.description)

    def test_refresh_token_invalid_token(self):
        api.create_dot_access_token(HttpRequest(), self.user, self.client)
        with self.assertRaises(api.OAuth2Error) as error:
            api.refresh_dot_access_token(
                HttpRequest(), self.client.client_id, 'invalid_refresh_token',
            )
        self.assertIn('invalid_grant', error.exception.description)