mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-16 11:12:21 +03:00
Fix the response status code when authenticating with wrong credentials
This conforms to RFC9110, see https://www.rfc-editor.org/rfc/rfc9110#section-15.5.2-2
This commit is contained in:
parent
17e95604f5
commit
754010859b
|
@ -2,6 +2,7 @@ from django.contrib.auth import authenticate
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from rest_framework.exceptions import AuthenticationFailed
|
||||||
|
|
||||||
|
|
||||||
class AuthTokenSerializer(serializers.Serializer):
|
class AuthTokenSerializer(serializers.Serializer):
|
||||||
|
@ -32,8 +33,7 @@ class AuthTokenSerializer(serializers.Serializer):
|
||||||
# users. (Assuming the default ModelBackend authentication
|
# users. (Assuming the default ModelBackend authentication
|
||||||
# backend.)
|
# backend.)
|
||||||
if not user:
|
if not user:
|
||||||
msg = _('Unable to log in with provided credentials.')
|
raise AuthenticationFailed()
|
||||||
raise serializers.ValidationError(msg, code='authorization')
|
|
||||||
else:
|
else:
|
||||||
msg = _('Must include "username" and "password".')
|
msg = _('Must include "username" and "password".')
|
||||||
raise serializers.ValidationError(msg, code='authorization')
|
raise serializers.ValidationError(msg, code='authorization')
|
||||||
|
|
|
@ -463,8 +463,6 @@ class APIView(View):
|
||||||
|
|
||||||
if auth_header:
|
if auth_header:
|
||||||
exc.auth_header = auth_header
|
exc.auth_header = auth_header
|
||||||
else:
|
|
||||||
exc.status_code = status.HTTP_403_FORBIDDEN
|
|
||||||
|
|
||||||
exception_handler = self.get_exception_handler()
|
exception_handler = self.get_exception_handler()
|
||||||
|
|
||||||
|
|
|
@ -281,7 +281,7 @@ class SessionAuthTests(TestCase):
|
||||||
Ensure POSTing form over session authentication without logged in user fails.
|
Ensure POSTing form over session authentication without logged in user fails.
|
||||||
"""
|
"""
|
||||||
response = self.csrf_client.post('/session/', {'example': 'example'})
|
response = self.csrf_client.post('/session/', {'example': 'example'})
|
||||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||||
|
|
||||||
|
|
||||||
class BaseTokenAuthTests:
|
class BaseTokenAuthTests:
|
||||||
|
@ -440,7 +440,7 @@ class TokenAuthTests(BaseTokenAuthTests, TestCase):
|
||||||
{'username': self.username, 'password': "badpass"},
|
{'username': self.username, 'password': "badpass"},
|
||||||
format='json'
|
format='json'
|
||||||
)
|
)
|
||||||
assert response.status_code == 400
|
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||||
|
|
||||||
def test_token_login_json_missing_fields(self):
|
def test_token_login_json_missing_fields(self):
|
||||||
"""Ensure token login view using JSON POST fails if missing fields."""
|
"""Ensure token login view using JSON POST fails if missing fields."""
|
||||||
|
@ -490,7 +490,7 @@ class IncorrectCredentialsTests(TestCase):
|
||||||
permission_classes=()
|
permission_classes=()
|
||||||
)
|
)
|
||||||
response = view(request)
|
response = view(request)
|
||||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||||
assert response.data == {'detail': 'Bad credentials'}
|
assert response.data == {'detail': 'Bad credentials'}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
|
|
||||||
|
from rest_framework import status
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
from rest_framework.test import APIClient
|
from rest_framework.test import APIClient
|
||||||
|
|
||||||
|
@ -21,14 +22,14 @@ class AnonymousUserTests(TestCase):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
self.client.get('/basicviewset')
|
self.client.get('/basicviewset')
|
||||||
|
|
||||||
def test_get_returns_http_forbidden_when_anonymous_user(self):
|
def test_get_returns_http_unauthorized_when_anonymous_user(self):
|
||||||
old_permissions = BasicModelWithUsersViewSet.permission_classes
|
old_permissions = BasicModelWithUsersViewSet.permission_classes
|
||||||
BasicModelWithUsersViewSet.permission_classes = [IsAuthenticated, OrganizationPermissions]
|
BasicModelWithUsersViewSet.permission_classes = [IsAuthenticated, OrganizationPermissions]
|
||||||
|
|
||||||
response = self.client.get('/basicviewset')
|
response = self.client.get('/basicviewset')
|
||||||
|
|
||||||
BasicModelWithUsersViewSet.permission_classes = old_permissions
|
BasicModelWithUsersViewSet.permission_classes = old_permissions
|
||||||
self.assertEqual(response.status_code, 403)
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ROOT_URLCONF='tests.browsable_api.auth_urls')
|
@override_settings(ROOT_URLCONF='tests.browsable_api.auth_urls')
|
||||||
|
|
|
@ -132,7 +132,7 @@ class DecoratorTestCase(TestCase):
|
||||||
|
|
||||||
request = self.factory.get('/')
|
request = self.factory.get('/')
|
||||||
response = view(request)
|
response = view(request)
|
||||||
assert response.status_code == status.HTTP_403_FORBIDDEN
|
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||||
|
|
||||||
def test_throttle_classes(self):
|
def test_throttle_classes(self):
|
||||||
class OncePerDayUserThrottle(UserRateThrottle):
|
class OncePerDayUserThrottle(UserRateThrottle):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user