From 08b6931103a13280cbfb22fd3d0a7fcad07cd23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Ericson?= Date: Fri, 6 Feb 2015 05:35:01 -0300 Subject: [PATCH] get_authenticate_header should look for unauthenticated request in all authenticators --- rest_framework/views.py | 4 +++- tests/test_authentication.py | 18 ++++++++++++++++++ tests/test_decorators.py | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/rest_framework/views.py b/rest_framework/views.py index bc870417f..8221073c5 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -7,6 +7,7 @@ from django.core.exceptions import PermissionDenied from django.http import Http404 from django.utils.encoding import smart_text from django.views.decorators.csrf import csrf_exempt +from django.utils.six.moves import filter as ifilter from rest_framework import status, exceptions from rest_framework.compat import HttpResponseBase, View from rest_framework.request import Request @@ -155,7 +156,8 @@ class APIView(View): """ authenticators = self.get_authenticators() if authenticators: - return authenticators[0].authenticate_header(request) + headers = (authenticator.authenticate_header(request) for authenticator in authenticators) + return next(ifilter(lambda x: x, headers), None) def get_parser_context(self, http_request): """ diff --git a/tests/test_authentication.py b/tests/test_authentication.py index caabcc214..8f62b283e 100644 --- a/tests/test_authentication.py +++ b/tests/test_authentication.py @@ -49,6 +49,8 @@ urlpatterns = patterns( (r'^session/$', MockView.as_view(authentication_classes=[SessionAuthentication])), (r'^basic/$', MockView.as_view(authentication_classes=[BasicAuthentication])), (r'^token/$', MockView.as_view(authentication_classes=[TokenAuthentication])), + (r'^token2/$', MockView.as_view(authentication_classes=[TokenAuthentication, SessionAuthentication])), + (r'^token3/$', MockView.as_view(authentication_classes=[SessionAuthentication, TokenAuthentication])), (r'^auth-token/$', 'rest_framework.authtoken.views.obtain_auth_token'), (r'^oauth/$', MockView.as_view(authentication_classes=[OAuthAuthentication])), ( @@ -218,6 +220,22 @@ class TokenAuthTests(TestCase): response = self.csrf_client.post('/token/', {'example': 'example'}, format='json') self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + def test_post_failing_token_auth_when_token_is_first_auth_class(self): + """ + Ensure POSTing with token auth without correct credentials fails with 401 + when TokenSession is the first in authentication_classes + """ + response = self.csrf_client.post('/token2/', {'example': 'example'}) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + + def test_post_failing_token_auth_when_token_is_second_auth_class(self): + """ + Ensure POSTing with token auth without correct credentials fails with 401 + when TokenSession is not the first in authentication_classes + """ + response = self.csrf_client.post('/token3/', {'example': 'example'}) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + def test_token_has_auto_assigned_key_if_none_provided(self): """Ensure creating a token with no key will auto-assign a key""" self.token.delete() diff --git a/tests/test_decorators.py b/tests/test_decorators.py index 195f0ba3e..05e426dd1 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -138,7 +138,7 @@ class DecoratorTestCase(TestCase): request = self.factory.get('/') response = view(request) - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) def test_throttle_classes(self): class OncePerDayUserThrottle(UserRateThrottle):