Opened 4 days ago

Closed 3 days ago

#36195 closed Bug (worksforme)

redirect_to_login Misinterprets next Parameter with Multiple Query Parameters

Reported by: Antoni Czaplicki Owned by:
Component: contrib.auth Version: 5.1
Severity: Normal Keywords: auth redirect_to_login query
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

There is a bug in the redirect_to_login function in django.contrib.auth.views. When the next parameter itself contains multiple query parameters (separated by &), they are incorrectly interpreted as part of the main login URL’s query parameters instead of being properly escaped as part of the next value.

Steps to Reproduce:

  1. Configure Django view with required login decorator
  2. Attempt to access a protected view with a next parameter containing multiple query parameters, e.g.:

/protected-view/?foo=1&bar=2

  1. The user is redirected to the login page, where the generated login URL is:

/login/?next=/protected-view/?foo=1&bar=2

This is incorrect because &bar=2 is interpreted as a separate query parameter for /login/ instead of part of the next value.

  1. After login, the user is redirected to:

/protected-view/?foo=1

Instead of the expected:

/protected-view/?foo=1&bar=2

Expected Behavior:
Ampersands in next parameter should be properly escaped so that it is treated as a single query parameter in the login URL. It should appear as:

/login/?next=/protected-view/?foo=1%26bar=2

so that after login, Django correctly redirects to:

/protected-view/?foo=1&bar=2

Affected Code:
The issue originates in redirect_to_login:

https://github.com/django/django/blob/2d34ebe49a25d0974392583d5bbd954baf742a32/django/contrib/auth/views.py#L180

Change History (1)

comment:1 by Sarah Boyce, 3 days ago

Resolution: worksforme
Status: newclosed

Checked via a test and a test project, the parameters are escaped for me

  • tests/test_client/tests.py

    a b class ClientTest(TestCase):  
    557557        self.assertEqual(response.status_code, 200)
    558558        self.assertEqual(response.context["user"].username, "testclient")
    559559
     560    def test_view_with_login_with_query_parameter(self):
     561        response = self.client.get("/login_protected_view/?foo=1&bar=2")
     562        self.assertRedirects(response, "/accounts/login/?next=/login_protected_view/%3Ffoo%3D1%26bar%3D2")
     563
    560564    @override_settings(
    561565        INSTALLED_APPS=["django.contrib.auth"],
    562566        SESSION_ENGINE="django.contrib.sessions.backends.file",
Note: See TracTickets for help on using tickets.
Back to Top