diff --git a/oauth2_provider/views/introspect.py b/oauth2_provider/views/introspect.py index 5474c3a7e..d3fb18b51 100644 --- a/oauth2_provider/views/introspect.py +++ b/oauth2_provider/views/introspect.py @@ -35,6 +35,11 @@ def get_token_response(token_value=None): ) except ObjectDoesNotExist: return JsonResponse({"active": False}, status=200) + except AttributeError: + return JsonResponse( + {"error": "invalid_request", "error_description": "Token parameter is missing."}, + status=400, + ) else: if token.is_valid(): data = { diff --git a/tests/test_introspection_view.py b/tests/test_introspection_view.py index 3db23bbcd..ad7d8983d 100644 --- a/tests/test_introspection_view.py +++ b/tests/test_introspection_view.py @@ -279,6 +279,20 @@ def test_view_post_notexisting_token(self): }, ) + def test_view_post_no_token(self): + """ + Test that when you pass no token HTTP 400 is returned + """ + auth_headers = { + "HTTP_AUTHORIZATION": "Bearer " + self.resource_server_token.token, + } + response = self.client.post(reverse("oauth2_provider:introspect"), **auth_headers) + + self.assertEqual(response.status_code, 400) + content = response.json() + self.assertIsInstance(content, dict) + self.assertEqual(content["error"], "invalid_request") + def test_view_post_valid_client_creds_basic_auth(self): """Test HTTP basic auth working""" auth_headers = get_basic_auth_header(self.application.client_id, CLEARTEXT_SECRET) diff --git a/tox.ini b/tox.ini index 303b0d51d..d5cf8d2dc 100644 --- a/tox.ini +++ b/tox.ini @@ -5,10 +5,10 @@ envlist = docs, lint, sphinxlint, - py{38,39,310,311,312}-dj42, - py{310,311,312}-dj50, - py{310,311,312}-dj51, - py{310,311,312}-djmain, + py{38,39,310,311,312,313}-dj42, + py{310,311,312,313}-dj50, + py{310,311,312,313}-dj51, + py{310,311,312,313}-djmain, py39-multi-db-dj-42 [gh-actions] @@ -18,6 +18,7 @@ python = 3.10: py310 3.11: py311 3.12: py312 + 3.13: py313 [gh-actions:env] DJANGO = @@ -54,7 +55,7 @@ deps = passenv = PYTEST_ADDOPTS -[testenv:py{310,311,312}-djmain] +[testenv:py{310,311,312,313}-djmain] ignore_errors = true ignore_outcome = true