Skip to content

Commit 10842aa

Browse files
Prevent basic auth pages from being indexed (#28)
1 parent 1800687 commit 10842aa

File tree

3 files changed

+32
-21
lines changed

3 files changed

+32
-21
lines changed

baipw/middleware.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import ipaddress
22

33
from django.conf import settings
4-
from django.core.exceptions import PermissionDenied
54
from django.utils.module_loading import import_string
65

76
from .exceptions import Unauthorized
@@ -38,7 +37,7 @@ def process_request(self, request):
3837
if self._is_basic_auth_configured():
3938
return self._basic_auth_response(request)
4039
# Otherwise just deny the access to the website
41-
raise PermissionDenied
40+
return self.get_error_response(request)
4241

4342
@property
4443
def basic_auth_login(self):
@@ -48,17 +47,24 @@ def basic_auth_login(self):
4847
def basic_auth_password(self):
4948
return getattr(settings, "BASIC_AUTH_PASSWORD", None)
5049

51-
def get_response_class(self):
50+
def get_error_response(self, request):
5251
try:
53-
return import_string(settings.BASIC_AUTH_RESPONSE_CLASS)
52+
response_class = import_string(settings.BASIC_AUTH_RESPONSE_CLASS)
5453
except AttributeError:
55-
return HttpUnauthorizedResponse
54+
response_class = HttpUnauthorizedResponse
55+
56+
response = response_class(request=request)
57+
58+
# Ensure pages can't be indexed, even if authentication is enabled.
59+
response.headers["X-Robots-Tag"] = "noindex"
60+
61+
return response
5662

5763
def _basic_auth_response(self, request):
5864
try:
5965
authorize(request, self.basic_auth_login, self.basic_auth_password)
6066
except Unauthorized:
61-
return self.get_response_class()(request=request)
67+
return self.get_error_response(request)
6268

6369
def _get_client_ip(self, request):
6470
function_path = getattr(

baipw/tests/test_integration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def setUp(self):
3232

3333
def test_basic_auth_not_configured(self):
3434
response = self.client.get("/")
35-
self.assertEqual(response.status_code, 403)
35+
self.assertEqual(response.status_code, 401)
3636

3737
@test.override_settings(
3838
BASIC_AUTH_LOGIN="test",

baipw/tests/test_middleware.py

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from unittest import mock
22
from unittest.mock import MagicMock
33

4-
from django.core.exceptions import PermissionDenied
54
from django.test import RequestFactory, TestCase, override_settings
65

76
from baipw.middleware import BasicAuthIPWhitelistMiddleware
@@ -18,8 +17,9 @@ def setUp(self):
1817

1918
class TestMiddleware(TestCaseMixin, TestCase):
2019
def test_no_settings_returns_permission_denied(self):
21-
with self.assertRaises(PermissionDenied):
22-
self.middleware(self.request)
20+
response = self.middleware(self.request)
21+
self.assertEqual(response.status_code, 401)
22+
self.assertEqual(response.headers["X-Robots-Tag"], "noindex")
2323

2424
@override_settings(
2525
BASIC_AUTH_LOGIN="testlogin",
@@ -28,6 +28,7 @@ def test_no_settings_returns_permission_denied(self):
2828
def test_basic_auth_returns_401(self):
2929
response = self.middleware(self.request)
3030
self.assertEqual(response.status_code, 401)
31+
self.assertEqual(response.headers["X-Robots-Tag"], "noindex")
3132

3233
@override_settings(
3334
BASIC_AUTH_LOGIN="testlogin",
@@ -236,17 +237,17 @@ def test_http_host_whitelist_fails_check_when_configured_(self):
236237

237238
@override_settings(BASIC_AUTH_WHITELISTED_HTTP_HOSTS=["kernel.org", "dgg.gg"])
238239
def test_http_host_whitelist_fails_check_with_no_host(self):
239-
with self.assertRaises(PermissionDenied):
240-
self.middleware(self.request)
240+
response = self.middleware(self.request)
241+
self.assertEqual(response.status_code, 401)
241242

242243
@override_settings(
243244
ALLOWED_HOSTS=["www.example.com"],
244245
BASIC_AUTH_WHITELISTED_HTTP_HOSTS=["kernel.org", "dgg.gg"],
245246
)
246247
def test_http_host_whitelist_fails_check_with_wrong_host(self):
247248
self.request.META["HTTP_HOST"] = "www.example.com"
248-
with self.assertRaises(PermissionDenied):
249-
self.middleware(self.request)
249+
response = self.middleware(self.request)
250+
self.assertEqual(response.status_code, 401)
250251

251252
@override_settings(
252253
BASIC_AUTH_LOGIN="somelogin",
@@ -300,14 +301,14 @@ def test_path_whitelist_fails_check_when_configured(self):
300301

301302
@override_settings(BASIC_AUTH_WHITELISTED_PATHS=["ham/", "eggs/"])
302303
def test_path_whitelist_fails_check_for_parent_path(self):
303-
with self.assertRaises(PermissionDenied):
304-
self.middleware(self.request)
304+
response = self.middleware(self.request)
305+
self.assertEqual(response.status_code, 401)
305306

306307
@override_settings(BASIC_AUTH_WHITELISTED_PATHS=["ham/", "eggs/"])
307308
def test_path_whitelist_fails_check_with_wrong_path(self):
308309
self.request.path = "spam/"
309-
with self.assertRaises(PermissionDenied):
310-
self.middleware(self.request)
310+
response = self.middleware(self.request)
311+
self.assertEqual(response.status_code, 401)
311312

312313
@override_settings(
313314
BASIC_AUTH_LOGIN="somelogin",
@@ -330,11 +331,15 @@ def test_path_whitelist_check_when_settings_empty(self):
330331

331332
class TestResponseClass(TestCaseMixin, TestCase):
332333
def test_get_response_class_when_none_set(self):
333-
self.assertIs(self.middleware.get_response_class(), HttpUnauthorizedResponse)
334+
self.assertIsInstance(
335+
self.middleware.get_error_response(self.request), HttpUnauthorizedResponse
336+
)
334337

335338
@override_settings(BASIC_AUTH_RESPONSE_CLASS="baipw.tests.response.TestResponse")
336339
def test_get_response_class_when_set(self):
337-
self.assertIs(self.middleware.get_response_class(), TestResponse)
340+
self.assertIsInstance(
341+
self.middleware.get_error_response(self.request), TestResponse
342+
)
338343

339344
@override_settings(
340345
BASIC_AUTH_LOGIN="testlogin",
@@ -343,5 +348,5 @@ def test_get_response_class_when_set(self):
343348
)
344349
def test_middleware_when_custom_response_set(self):
345350
response = self.middleware(self.request)
346-
self.assertIs(response.__class__, TestResponse)
351+
self.assertIsInstance(response, TestResponse)
347352
self.assertEqual(response.content, b"Test message. :P")

0 commit comments

Comments
 (0)