def setUp(self): self.csrf_client = APIClient(enforce_csrf_checks=True) self.username = '******' self.email = '*****@*****.**' self.password = '******' self.user = User.objects.create_user(self.username, self.email, self.password)
def test_refresh_jwt(self): """ Test getting a refreshed token from original token works No date/time modifications are neccessary because it is assumed that this operation will take less than 300 seconds. """ client = APIClient(enforce_csrf_checks=True) orig_token = self.get_token() orig_token_decoded = utils.jwt_decode_handler(orig_token) expected_orig_iat = timegm(datetime.utcnow().utctimetuple()) # Make sure 'orig_iat' exists and is the current time (give some slack) orig_iat = orig_token_decoded['orig_iat'] self.assertLessEqual(orig_iat - expected_orig_iat, 1) time.sleep(1) # Now try to get a refreshed token response = client.post('/auth-token-refresh/', {'token': orig_token}, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) new_token = response.data['token'] new_token_decoded = utils.jwt_decode_handler(new_token) # Make sure 'orig_iat' on the new token is same as original self.assertEquals(new_token_decoded['orig_iat'], orig_iat) self.assertGreater(new_token_decoded['exp'], orig_token_decoded['exp'])
def test_token_login_form(self): """Ensure token login view using form POST works.""" client = APIClient(enforce_csrf_checks=True) response = client.post('/auth-token/', { 'username': self.username, 'password': self.password }) assert response.status_code == status.HTTP_200_OK assert response.data['token'] == self.key
def setUp(self): self.csrf_client = APIClient(enforce_csrf_checks=True) self.username = '******' self.email = '*****@*****.**' self.password = '******' self.user = User.objects.create_user(self.username, self.email, self.password) self.key = 'abcd1234' self.token = self.model.objects.create(key=self.key, user=self.user)
def test_jwt_login_json_missing_fields(self): """ Ensure JWT login view using JSON POST fails if missing fields. """ client = APIClient(enforce_csrf_checks=True) response = client.post('/auth-token/', {'username': self.username}, format='json') self.assertEqual(response.status_code, 400)
class DropdownWithAuthTests(TestCase): """Tests correct dropdown behaviour with Auth views enabled.""" def setUp(self): self.client = APIClient(enforce_csrf_checks=True) self.username = '******' self.email = '*****@*****.**' self.password = '******' self.user = User.objects.create_user(self.username, self.email, self.password) def tearDown(self): self.client.logout() def test_name_shown_when_logged_in(self): self.client.login(username=self.username, password=self.password) response = self.client.get('/') content = response.content.decode('utf8') assert 'john' in content def test_logout_shown_when_logged_in(self): self.client.login(username=self.username, password=self.password) response = self.client.get('/') content = response.content.decode('utf8') assert '>Log out<' in content def test_login_shown_when_logged_out(self): response = self.client.get('/') content = response.content.decode('utf8') assert '>Log in<' in content
def test_jwt_login_using_zero(self): """ Test to reproduce issue #33 """ client = APIClient(enforce_csrf_checks=True) data = {'username': '******', 'password': '******'} response = client.post('/auth-token/', data, format='json') self.assertEqual(response.status_code, 400)
def test_explicitly_enforce_csrf_checks(self): """ The test client can enforce CSRF checks. """ client = APIClient(enforce_csrf_checks=True) User.objects.create_user('example', '*****@*****.**', 'password') client.login(username='******', password='******') response = client.post('/view/') expected = {'detail': 'CSRF Failed: CSRF cookie not set.'} assert response.status_code == 403 assert response.data == expected
def test_jwt_login_json_bad_creds(self): """ Ensure JWT login view using JSON POST fails if bad credentials are used. """ client = APIClient(enforce_csrf_checks=True) self.data['password'] = '******' response = client.post('/auth-token/', self.data, format='json') self.assertEqual(response.status_code, 400)
def test_jwt_login_json(self): """ Ensure JWT login view using JSON POST works. """ client = APIClient(enforce_csrf_checks=True) response = client.post('/auth-token/', self.data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) decoded_payload = utils.jwt_decode_handler(response.data['token']) self.assertEqual(decoded_payload['user_id'], str(self.user.id))
def test_token_login_json_bad_creds(self): """ Ensure token login view using JSON POST fails if bad credentials are used """ client = APIClient(enforce_csrf_checks=True) response = client.post('/auth-token/', { 'username': self.username, 'password': "******" }, format='json') assert response.status_code == 400
def test_verify_jwt_fails_with_bad_token(self): """ Test that an invalid token will fail with the correct error. """ client = APIClient(enforce_csrf_checks=True) token = "i am not a correctly formed token" response = client.post('/auth-token-verify/', {'token': token}, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertRegexpMatches(response.data['non_field_errors'][0], 'Error decoding signature')
def test_verify_jwt_with_pub_pvt_key(self): """ Test that a token can be signed with asymmetrics keys """ client = APIClient(enforce_csrf_checks=True) orig_token = self.get_token() # Now try to get a refreshed token response = client.post('/auth-token-verify/', {'token': orig_token}, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['token'], orig_token)
def test_verify_jwt(self): """ Test that a valid, non-expired token will return a 200 response and itself when passed to the validation endpoint. """ client = APIClient(enforce_csrf_checks=True) orig_token = self.get_token() # Now try to get a refreshed token response = client.post('/auth-token-verify/', {'token': orig_token}, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['token'], orig_token)
def test_verify_jwt_fails_with_expired_token(self): """ Test that an expired token will fail with the correct error. """ client = APIClient(enforce_csrf_checks=True) # Make an expired token.. token = self.create_token(self.user, exp=datetime.utcnow() - timedelta(seconds=5), orig_iat=datetime.utcnow() - timedelta(hours=1)) response = client.post('/auth-token-verify/', {'token': token}, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertRegexpMatches(response.data['non_field_errors'][0], 'Signature has expired')
def test_refresh_jwt_after_refresh_expiration(self): """ Test that token can't be refreshed after token refresh limit """ client = APIClient(enforce_csrf_checks=True) orig_iat = (datetime.utcnow() - api_settings.JWT_REFRESH_EXPIRATION_DELTA - timedelta(seconds=5)) token = self.create_token(self.user, exp=datetime.utcnow() + timedelta(hours=1), orig_iat=orig_iat) response = client.post('/auth-token-refresh/', {'token': token}, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.data['non_field_errors'][0], 'Refresh has expired.')
def test_verify_jwt_fails_with_missing_user(self): """ Test that an invalid token will fail with a user that does not exist. """ client = APIClient(enforce_csrf_checks=True) user = User.objects.create_user(email='*****@*****.**', username='******', password='******') token = self.create_token(user) # Delete the user used to make the token user.delete() response = client.post('/auth-token-verify/', {'token': token}, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertRegexpMatches(response.data['non_field_errors'][0], "User doesn't exist")
def test_jwt_login_with_expired_token(self): """ Ensure JWT login view works even if expired token is provided """ payload = utils.jwt_payload_handler(self.user) payload['exp'] = 1 token = utils.jwt_encode_handler(payload) auth = 'JWT {0}'.format(token) client = APIClient(enforce_csrf_checks=True) response = client.post('/auth-token/', self.data, HTTP_AUTHORIZATION=auth, format='json') decoded_payload = utils.jwt_decode_handler(response.data['token']) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(decoded_payload['username'], self.username)
def test_verify_jwt_fails_with_bad_pvt_key(self): """ Test that an mismatched private key token will fail with the correct error. """ # Generate a new private key private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) # Don't set the private key api_settings.JWT_PRIVATE_KEY = private_key client = APIClient(enforce_csrf_checks=True) orig_token = self.get_token() # Now try to get a refreshed token response = client.post('/auth-token-verify/', {'token': orig_token}, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertRegexpMatches(response.data['non_field_errors'][0], 'Error decoding signature')
def test_duplicate_request_stream_parsing_exception(self): """ Check assumption that duplicate stream parsing will result in a `RawPostDataException` being raised. """ response = APIClient().post('/echo/', data={'a': 'b'}, format='json') request = response.renderer_context['request'] # ensure that request stream was consumed by json parser assert request.content_type.startswith('application/json') assert response.data == {'a': 'b'} # pass same HttpRequest to view, stream already consumed with pytest.raises(RawPostDataException): EchoView.as_view()(request._request)
class TestContentParsingWithAuthentication(TestCase): def setUp(self): self.csrf_client = APIClient(enforce_csrf_checks=True) self.username = '******' self.email = '*****@*****.**' self.password = '******' self.user = User.objects.create_user(self.username, self.email, self.password) def test_user_logged_in_authentication_has_POST_when_not_logged_in(self): """ Ensures request.POST exists after SessionAuthentication when user doesn't log in. """ content = {'example': 'example'} response = self.client.post('/', content) assert status.HTTP_200_OK == response.status_code response = self.csrf_client.post('/', content) assert status.HTTP_200_OK == response.status_code
def test_duplicate_request_form_data_access(self): """ Form data is copied to the underlying django request for middleware and file closing reasons. Duplicate processing of a request with form data is 'safe' in so far as accessing `request.POST` does not trigger the duplicate stream parse exception. """ response = APIClient().post('/echo/', data={'a': 'b'}) request = response.renderer_context['request'] # ensure that request stream was consumed by form parser assert request.content_type.startswith('multipart/form-data') assert response.data == {'a': ['b']} # pass same HttpRequest to view, form data set on underlying request response = EchoView.as_view()(request._request) request = response.renderer_context['request'] # ensure that request stream was consumed by form parser assert request.content_type.startswith('multipart/form-data') assert response.data == {'a': ['b']}
def setUp(self): self.csrf_client = APIClient(enforce_csrf_checks=True) self.username = '******' self.email = '*****@*****.**' self.user = User.objects.create_user(self.username, self.email)
class BasicAuthTests(TestCase): """Basic authentication""" def setUp(self): self.csrf_client = APIClient(enforce_csrf_checks=True) self.username = '******' self.email = '*****@*****.**' self.password = '******' self.user = User.objects.create_user(self.username, self.email, self.password) def test_post_form_passing_basic_auth(self): """Ensure POSTing json over basic auth with correct credentials passes and does not require CSRF""" credentials = ('%s:%s' % (self.username, self.password)) base64_credentials = base64.b64encode( credentials.encode(HTTP_HEADER_ENCODING)).decode( HTTP_HEADER_ENCODING) auth = 'Basic %s' % base64_credentials response = self.csrf_client.post('/basic/', {'example': 'example'}, HTTP_AUTHORIZATION=auth) assert response.status_code == status.HTTP_200_OK def test_post_json_passing_basic_auth(self): """Ensure POSTing form over basic auth with correct credentials passes and does not require CSRF""" credentials = ('%s:%s' % (self.username, self.password)) base64_credentials = base64.b64encode( credentials.encode(HTTP_HEADER_ENCODING)).decode( HTTP_HEADER_ENCODING) auth = 'Basic %s' % base64_credentials response = self.csrf_client.post('/basic/', {'example': 'example'}, format='json', HTTP_AUTHORIZATION=auth) assert response.status_code == status.HTTP_200_OK def test_regression_handle_bad_base64_basic_auth_header(self): """Ensure POSTing JSON over basic auth with incorrectly padded Base64 string is handled correctly""" # regression test for issue in 'mind_core.authentication.BasicAuthentication.authenticate' # https://github.com/encode/django-rest-framework/issues/4089 auth = 'Basic =a=' response = self.csrf_client.post('/basic/', {'example': 'example'}, format='json', HTTP_AUTHORIZATION=auth) assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_post_form_failing_basic_auth(self): """Ensure POSTing form over basic auth without correct credentials fails""" response = self.csrf_client.post('/basic/', {'example': 'example'}) assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_post_json_failing_basic_auth(self): """Ensure POSTing json over basic auth without correct credentials fails""" response = self.csrf_client.post('/basic/', {'example': 'example'}, format='json') assert response.status_code == status.HTTP_401_UNAUTHORIZED assert response['WWW-Authenticate'] == 'Basic realm="api"' def test_fail_post_if_credentials_are_missing(self): response = self.csrf_client.post('/basic/', {'example': 'example'}, HTTP_AUTHORIZATION='Basic ') assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_fail_post_if_credentials_contain_spaces(self): response = self.csrf_client.post('/basic/', {'example': 'example'}, HTTP_AUTHORIZATION='Basic foo bar') assert response.status_code == status.HTTP_401_UNAUTHORIZED
class BaseTokenAuthTests(object): """Token authentication""" model = None path = None header_prefix = 'Token ' def setUp(self): self.csrf_client = APIClient(enforce_csrf_checks=True) self.username = '******' self.email = '*****@*****.**' self.password = '******' self.user = User.objects.create_user(self.username, self.email, self.password) self.key = 'abcd1234' self.token = self.model.objects.create(key=self.key, user=self.user) def test_post_form_passing_token_auth(self): """ Ensure POSTing json over token auth with correct credentials passes and does not require CSRF """ auth = self.header_prefix + self.key response = self.csrf_client.post(self.path, {'example': 'example'}, HTTP_AUTHORIZATION=auth) assert response.status_code == status.HTTP_200_OK def test_fail_authentication_if_user_is_not_active(self): user = User.objects.create_user('foo', 'bar', 'baz') user.is_active = False user.save() self.model.objects.create(key='foobar_token', user=user) response = self.csrf_client.post( self.path, {'example': 'example'}, HTTP_AUTHORIZATION=self.header_prefix + 'foobar_token') assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_fail_post_form_passing_nonexistent_token_auth(self): # use a nonexistent token key auth = self.header_prefix + 'wxyz6789' response = self.csrf_client.post(self.path, {'example': 'example'}, HTTP_AUTHORIZATION=auth) assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_fail_post_if_token_is_missing(self): response = self.csrf_client.post(self.path, {'example': 'example'}, HTTP_AUTHORIZATION=self.header_prefix) assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_fail_post_if_token_contains_spaces(self): response = self.csrf_client.post( self.path, {'example': 'example'}, HTTP_AUTHORIZATION=self.header_prefix + 'foo bar') assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_fail_post_form_passing_invalid_token_auth(self): # add an 'invalid' unicode character auth = self.header_prefix + self.key + "¸" response = self.csrf_client.post(self.path, {'example': 'example'}, HTTP_AUTHORIZATION=auth) assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_post_json_passing_token_auth(self): """ Ensure POSTing form over token auth with correct credentials passes and does not require CSRF """ auth = self.header_prefix + self.key response = self.csrf_client.post(self.path, {'example': 'example'}, format='json', HTTP_AUTHORIZATION=auth) assert response.status_code == status.HTTP_200_OK def test_post_json_makes_one_db_query(self): """ Ensure that authenticating a user using a token performs only one DB query """ auth = self.header_prefix + self.key def func_to_test(): return self.csrf_client.post(self.path, {'example': 'example'}, format='json', HTTP_AUTHORIZATION=auth) self.assertNumQueries(1, func_to_test) def test_post_form_failing_token_auth(self): """ Ensure POSTing form over token auth without correct credentials fails """ response = self.csrf_client.post(self.path, {'example': 'example'}) assert response.status_code == status.HTTP_401_UNAUTHORIZED def test_post_json_failing_token_auth(self): """ Ensure POSTing json over token auth without correct credentials fails """ response = self.csrf_client.post(self.path, {'example': 'example'}, format='json') assert response.status_code == status.HTTP_401_UNAUTHORIZED
class TestAPITestClient(TestCase): def setUp(self): self.client = APIClient() def test_credentials(self): """ Setting `.credentials()` adds the required headers to each request. """ self.client.credentials(HTTP_AUTHORIZATION='example') for _ in range(0, 3): response = self.client.get('/view/') assert response.data['auth'] == 'example' def test_force_authenticate(self): """ Setting `.force_authenticate()` forcibly authenticates each request. """ user = User.objects.create_user('example', '*****@*****.**') self.client.force_authenticate(user) response = self.client.get('/view/') assert response.data['user'] == 'example' def test_force_authenticate_with_sessions(self): """ Setting `.force_authenticate()` forcibly authenticates each request. """ user = User.objects.create_user('example', '*****@*****.**') self.client.force_authenticate(user) # First request does not yet have an active session response = self.client.get('/session-view/') assert response.data['active_session'] is False # Subsequent requests have an active session response = self.client.get('/session-view/') assert response.data['active_session'] is True # Force authenticating as `None` should also logout the user session. self.client.force_authenticate(None) response = self.client.get('/session-view/') assert response.data['active_session'] is False def test_csrf_exempt_by_default(self): """ By default, the test client is CSRF exempt. """ User.objects.create_user('example', '*****@*****.**', 'password') self.client.login(username='******', password='******') response = self.client.post('/view/') assert response.status_code == 200 def test_explicitly_enforce_csrf_checks(self): """ The test client can enforce CSRF checks. """ client = APIClient(enforce_csrf_checks=True) User.objects.create_user('example', '*****@*****.**', 'password') client.login(username='******', password='******') response = client.post('/view/') expected = {'detail': 'CSRF Failed: CSRF cookie not set.'} assert response.status_code == 403 assert response.data == expected def test_can_logout(self): """ `logout()` resets stored credentials """ self.client.credentials(HTTP_AUTHORIZATION='example') response = self.client.get('/view/') assert response.data['auth'] == 'example' self.client.logout() response = self.client.get('/view/') assert response.data['auth'] == b'' def test_logout_resets_force_authenticate(self): """ `logout()` resets any `force_authenticate` """ user = User.objects.create_user('example', '*****@*****.**', 'password') self.client.force_authenticate(user) response = self.client.get('/view/') assert response.data['user'] == 'example' self.client.logout() response = self.client.get('/view/') assert response.data['user'] == '' def test_follow_redirect(self): """ Follow redirect by setting follow argument. """ response = self.client.get('/redirect-view/') assert response.status_code == 302 response = self.client.get('/redirect-view/', follow=True) assert response.redirect_chain is not None assert response.status_code == 200 response = self.client.post('/redirect-view/') assert response.status_code == 302 response = self.client.post('/redirect-view/', follow=True) assert response.redirect_chain is not None assert response.status_code == 200 response = self.client.put('/redirect-view/') assert response.status_code == 302 response = self.client.put('/redirect-view/', follow=True) assert response.redirect_chain is not None assert response.status_code == 200 response = self.client.patch('/redirect-view/') assert response.status_code == 302 response = self.client.patch('/redirect-view/', follow=True) assert response.redirect_chain is not None assert response.status_code == 200 response = self.client.delete('/redirect-view/') assert response.status_code == 302 response = self.client.delete('/redirect-view/', follow=True) assert response.redirect_chain is not None assert response.status_code == 200 response = self.client.options('/redirect-view/') assert response.status_code == 302 response = self.client.options('/redirect-view/', follow=True) assert response.redirect_chain is not None assert response.status_code == 200 def test_invalid_multipart_data(self): """ MultiPart encoding cannot support nested data, so raise a helpful error if the user attempts to do so. """ self.assertRaises( AssertionError, self.client.post, path='/view/', data={'valid': 123, 'invalid': {'a': 123}} ) def test_empty_post_uses_default_boolean_value(self): response = self.client.post( '/post-view/', data=None, content_type='application/json' ) assert response.status_code == 200 assert response.data == {"flag": True}
def setUp(self): self.client = APIClient()
class JSONWebTokenAuthenticationTests(TestCase): """JSON Web Token Authentication""" def setUp(self): self.csrf_client = APIClient(enforce_csrf_checks=True) self.username = '******' self.email = '*****@*****.**' self.user = User.objects.create_user(self.username, self.email) def test_post_form_passing_jwt_auth(self): """ Ensure POSTing form over JWT auth with correct credentials passes and does not require CSRF """ payload = utils.jwt_payload_handler(self.user) token = utils.jwt_encode_handler(payload) auth = 'JWT {0}'.format(token) response = self.csrf_client.post('/jwt/', {'example': 'example'}, HTTP_AUTHORIZATION=auth) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.content, b'mockview-post') # Ensure `authenticate` returned the decoded payload. self.assertEqual(response.wsgi_request.user, self.user) payload = response.wsgi_request.auth self.assertIsInstance(payload, dict) self.assertEqual(set(payload.keys()), {'user_id', 'username', 'exp', 'email'}) def test_post_json_passing_jwt_auth(self): """ Ensure POSTing JSON over JWT auth with correct credentials passes and does not require CSRF """ payload = utils.jwt_payload_handler(self.user) token = utils.jwt_encode_handler(payload) auth = 'JWT {0}'.format(token) response = self.csrf_client.post('/jwt/', {'example': 'example'}, HTTP_AUTHORIZATION=auth, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) def test_post_form_failing_jwt_auth(self): """ Ensure POSTing form over JWT auth without correct credentials fails """ response = self.csrf_client.post('/jwt/', {'example': 'example'}) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.assertEqual(response['WWW-Authenticate'], 'JWT realm="api"') def test_post_json_failing_jwt_auth(self): """ Ensure POSTing json over JWT auth without correct credentials fails """ response = self.csrf_client.post('/jwt/', {'example': 'example'}, format='json') self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.assertEqual(response['WWW-Authenticate'], 'JWT realm="api"') def test_post_no_jwt_header_failing_jwt_auth(self): """ Ensure POSTing over JWT auth without credentials fails """ auth = 'JWT' response = self.csrf_client.post('/jwt/', {'example': 'example'}, HTTP_AUTHORIZATION=auth, format='json') msg = 'Invalid Authorization header. No credentials provided.' self.assertEqual(response.data['detail'], msg) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.assertEqual(response['WWW-Authenticate'], 'JWT realm="api"') def test_post_invalid_jwt_header_failing_jwt_auth(self): """ Ensure POSTing over JWT auth without correct credentials fails """ auth = 'JWT abc abc' response = self.csrf_client.post('/jwt/', {'example': 'example'}, HTTP_AUTHORIZATION=auth, format='json') msg = ('Invalid Authorization header. Credentials string ' 'should not contain spaces.') self.assertEqual(response.data['detail'], msg) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.assertEqual(response['WWW-Authenticate'], 'JWT realm="api"') def test_post_expired_token_failing_jwt_auth(self): """ Ensure POSTing over JWT auth with expired token fails """ payload = utils.jwt_payload_handler(self.user) payload['exp'] = 1 token = utils.jwt_encode_handler(payload) auth = 'JWT {0}'.format(token) response = self.csrf_client.post('/jwt/', {'example': 'example'}, HTTP_AUTHORIZATION=auth, format='json') msg = 'Signature has expired.' self.assertEqual(response.data['detail'], msg) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.assertEqual(response['WWW-Authenticate'], 'JWT realm="api"') @override_settings(AUTH_USER_MODEL='tests.CustomUser') def test_post_form_failing_jwt_auth_changed_user_secret_key(self): """ Ensure changin secret key on USER level makes tokens invalid """ # fine tune settings api_settings.JWT_GET_USER_SECRET_KEY = get_jwt_secret tmp_user = CustomUser.objects.create(email='*****@*****.**') payload = utils.jwt_payload_handler(tmp_user) token = utils.jwt_encode_handler(payload) auth = 'JWT {0}'.format(token) response = self.csrf_client.post('/jwt/', {'example': 'example'}, HTTP_AUTHORIZATION=auth, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) # change token, verify tmp_user.jwt_secret = uuid.uuid4() tmp_user.save() response = self.csrf_client.post('/jwt/', {'example': 'example'}, HTTP_AUTHORIZATION=auth) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) # revert api settings api_settings.JWT_GET_USER_SECRET_KEY = DEFAULTS[ 'JWT_GET_USER_SECRET_KEY'] def test_post_invalid_token_failing_jwt_auth(self): """ Ensure POSTing over JWT auth with invalid token fails """ auth = 'JWT abc123' response = self.csrf_client.post('/jwt/', {'example': 'example'}, HTTP_AUTHORIZATION=auth, format='json') msg = 'Error decoding signature.' self.assertEqual(response.data['detail'], msg) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.assertEqual(response['WWW-Authenticate'], 'JWT realm="api"') @unittest.skipUnless(oauth2_provider, DJANGO_OAUTH2_PROVIDER_NOT_INSTALLED) def test_post_passing_jwt_auth_with_oauth2_priority(self): """ Ensure POSTing over JWT auth with correct credentials passes and does not require CSRF when OAuth2Authentication has priority on authentication_classes """ payload = utils.jwt_payload_handler(self.user) token = utils.jwt_encode_handler(payload) auth = 'JWT {0}'.format(token) response = self.csrf_client.post('/oauth2-jwt/', {'example': 'example'}, HTTP_AUTHORIZATION=auth, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK, response) @unittest.skipUnless(oauth2_provider, DJANGO_OAUTH2_PROVIDER_NOT_INSTALLED) def test_post_passing_oauth2_with_jwt_auth_priority(self): """ Ensure POSTing over OAuth2 with correct credentials passes and does not require CSRF when JSONWebTokenAuthentication has priority on authentication_classes """ Client = oauth2_provider.oauth2.models.Client AccessToken = oauth2_provider.oauth2.models.AccessToken oauth2_client = Client.objects.create( user=self.user, client_type=0, ) access_token = AccessToken.objects.create( user=self.user, client=oauth2_client, ) auth = 'Bearer {0}'.format(access_token.token) response = self.csrf_client.post('/jwt-oauth2/', {'example': 'example'}, HTTP_AUTHORIZATION=auth, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK, response) def test_post_form_passing_jwt_invalid_payload(self): """ Ensure POSTing json over JWT auth with invalid payload fails """ payload = dict(email=None) token = utils.jwt_encode_handler(payload) auth = 'JWT {0}'.format(token) response = self.csrf_client.post('/jwt/', {'example': 'example'}, HTTP_AUTHORIZATION=auth) msg = 'Invalid payload.' self.assertEqual(response.data['detail'], msg) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) def test_different_auth_header_prefix(self): """ Ensure using a different setting for `JWT_AUTH_HEADER_PREFIX` and with correct credentials passes. """ api_settings.JWT_AUTH_HEADER_PREFIX = 'Bearer' payload = utils.jwt_payload_handler(self.user) token = utils.jwt_encode_handler(payload) auth = 'Bearer {0}'.format(token) response = self.csrf_client.post('/jwt/', {'example': 'example'}, HTTP_AUTHORIZATION=auth, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) # Restore original settings api_settings.JWT_AUTH_HEADER_PREFIX = DEFAULTS[ 'JWT_AUTH_HEADER_PREFIX'] def test_post_form_failing_jwt_auth_different_auth_header_prefix(self): """ Ensure using a different setting for `JWT_AUTH_HEADER_PREFIX` and POSTing form over JWT auth without correct credentials fails and generated correct WWW-Authenticate header """ api_settings.JWT_AUTH_HEADER_PREFIX = 'Bearer' response = self.csrf_client.post('/jwt/', {'example': 'example'}) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.assertEqual(response['WWW-Authenticate'], 'Bearer realm="api"') # Restore original settings api_settings.JWT_AUTH_HEADER_PREFIX = DEFAULTS[ 'JWT_AUTH_HEADER_PREFIX']
class SessionAuthTests(TestCase): """User session authentication""" def setUp(self): self.csrf_client = APIClient(enforce_csrf_checks=True) self.non_csrf_client = APIClient(enforce_csrf_checks=False) self.username = '******' self.email = '*****@*****.**' self.password = '******' self.user = User.objects.create_user(self.username, self.email, self.password) def tearDown(self): self.csrf_client.logout() def test_login_view_renders_on_get(self): """ Ensure the login template renders for a basic GET. cf. [#1810](https://github.com/encode/django-rest-framework/pull/1810) """ response = self.csrf_client.get('/auth/login/') content = response.content.decode('utf8') assert '<label for="id_username">Username:</label>' in content def test_post_form_session_auth_failing_csrf(self): """ Ensure POSTing form over session authentication without CSRF token fails. """ self.csrf_client.login(username=self.username, password=self.password) response = self.csrf_client.post('/session/', {'example': 'example'}) assert response.status_code == status.HTTP_403_FORBIDDEN def test_post_form_session_auth_passing_csrf(self): """ Ensure POSTing form over session authentication with CSRF token succeeds. Regression test for #6088 """ from django.middleware.csrf import _get_new_csrf_token self.csrf_client.login(username=self.username, password=self.password) # Set the csrf_token cookie so that CsrfViewMiddleware._get_token() works token = _get_new_csrf_token() self.csrf_client.cookies[settings.CSRF_COOKIE_NAME] = token # Post the token matching the cookie value response = self.csrf_client.post('/session/', { 'example': 'example', 'csrfmiddlewaretoken': token, }) assert response.status_code == status.HTTP_200_OK def test_post_form_session_auth_passing(self): """ Ensure POSTing form over session authentication with logged in user and CSRF token passes. """ self.non_csrf_client.login(username=self.username, password=self.password) response = self.non_csrf_client.post('/session/', {'example': 'example'}) assert response.status_code == status.HTTP_200_OK def test_put_form_session_auth_passing(self): """ Ensure PUTting form over session authentication with logged in user and CSRF token passes. """ self.non_csrf_client.login(username=self.username, password=self.password) response = self.non_csrf_client.put('/session/', {'example': 'example'}) assert response.status_code == status.HTTP_200_OK def test_post_form_session_auth_failing(self): """ Ensure POSTing form over session authentication without logged in user fails. """ response = self.csrf_client.post('/session/', {'example': 'example'}) assert response.status_code == status.HTTP_403_FORBIDDEN
def get_token(self): client = APIClient(enforce_csrf_checks=True) response = client.post('/auth-token/', self.data, format='json') return response.data['token']