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 _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'], )
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)
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 _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)
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 _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'], )
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'], )
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 _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'], )
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'], )
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)
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)
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)
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)