Skip to content

Commit 9ba74f8

Browse files
Copilotkuboschek
andcommitted
Add unit tests for login redirect with next parameter
Co-authored-by: kuboschek <1071495+kuboschek@users.noreply.github.com>
1 parent 0d9253b commit 9ba74f8

1 file changed

Lines changed: 92 additions & 0 deletions

File tree

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
from __future__ import annotations
2+
3+
from django.test import TestCase, RequestFactory
4+
from django.contrib.auth import get_user_model
5+
from django.conf import settings
6+
from unittest import mock
7+
8+
from custom_auth.views import email_token_login
9+
from custom_auth.utils.auth import generate_login_token
10+
11+
User = get_user_model()
12+
13+
14+
class EmailTokenLoginRedirectTest(TestCase):
15+
"""Test that email token login respects the 'next' parameter"""
16+
17+
fixtures = ["registry/tests/fixtures/integration.json"]
18+
19+
def setUp(self):
20+
self.factory = RequestFactory()
21+
self.user = User.objects.get(username="Mounfem")
22+
23+
def test_redirect_with_next_parameter(self):
24+
"""Test that login redirects to the 'next' URL when provided"""
25+
token = generate_login_token(self.user)
26+
27+
# Create a POST request with a valid token and next parameter
28+
request = self.factory.post('/auth/magic/', {
29+
'token': token,
30+
'next': '/payments/'
31+
})
32+
33+
with mock.patch('custom_auth.views.authenticate', return_value=self.user):
34+
with mock.patch('custom_auth.views.login'):
35+
response = email_token_login(request)
36+
37+
# Should redirect to /payments/
38+
self.assertEqual(response.status_code, 302)
39+
self.assertEqual(response.url, '/payments/')
40+
41+
def test_redirect_without_next_parameter(self):
42+
"""Test that login redirects to LOGIN_REDIRECT_URL when 'next' is not provided"""
43+
token = generate_login_token(self.user)
44+
45+
# Create a POST request with a valid token but no next parameter
46+
request = self.factory.post('/auth/magic/', {
47+
'token': token
48+
})
49+
50+
with mock.patch('custom_auth.views.authenticate', return_value=self.user):
51+
with mock.patch('custom_auth.views.login'):
52+
response = email_token_login(request)
53+
54+
# Should redirect to LOGIN_REDIRECT_URL (default: '/')
55+
self.assertEqual(response.status_code, 302)
56+
self.assertEqual(response.url, settings.LOGIN_REDIRECT_URL)
57+
58+
def test_redirect_with_empty_next_parameter(self):
59+
"""Test that login redirects to LOGIN_REDIRECT_URL when 'next' is empty"""
60+
token = generate_login_token(self.user)
61+
62+
# Create a POST request with a valid token and empty next parameter
63+
request = self.factory.post('/auth/magic/', {
64+
'token': token,
65+
'next': ''
66+
})
67+
68+
with mock.patch('custom_auth.views.authenticate', return_value=self.user):
69+
with mock.patch('custom_auth.views.login'):
70+
response = email_token_login(request)
71+
72+
# Should redirect to LOGIN_REDIRECT_URL (default: '/')
73+
self.assertEqual(response.status_code, 302)
74+
self.assertEqual(response.url, settings.LOGIN_REDIRECT_URL)
75+
76+
def test_redirect_blocks_external_urls(self):
77+
"""Test that external URLs are blocked (security check)"""
78+
token = generate_login_token(self.user)
79+
80+
# Create a POST request with a valid token and external next URL
81+
request = self.factory.post('/auth/magic/', {
82+
'token': token,
83+
'next': 'https://evil.com/phishing'
84+
})
85+
86+
with mock.patch('custom_auth.views.authenticate', return_value=self.user):
87+
with mock.patch('custom_auth.views.login'):
88+
response = email_token_login(request)
89+
90+
# Should redirect to LOGIN_REDIRECT_URL, not the external URL
91+
self.assertEqual(response.status_code, 302)
92+
self.assertEqual(response.url, settings.LOGIN_REDIRECT_URL)

0 commit comments

Comments
 (0)