2727from django .core .exceptions import ImproperlyConfigured
2828from django .test import Client , TestCase , override_settings
2929from django .test .client import RequestFactory
30- from django .urls import reverse
30+ from django .urls import reverse , reverse_lazy
3131from django .utils .encoding import force_text
3232from djangosaml2 import views
3333from djangosaml2 .cache import OutstandingQueriesCache
3434from djangosaml2 .conf import get_config
3535from djangosaml2 .middleware import SamlSessionMiddleware
3636from djangosaml2 .tests import conf
37- from djangosaml2 .utils import (get_idp_sso_supported_bindings ,
37+ from djangosaml2 .utils import (get_fallback_login_redirect_url ,
38+ get_idp_sso_supported_bindings ,
3839 get_session_id_from_saml2 ,
3940 get_subject_id_from_saml2 ,
4041 saml2_from_httpredirect_request )
@@ -76,6 +77,23 @@ def test_get_config_missing_function(self):
7677 with self .assertRaisesMessage (ImproperlyConfigured , 'Module "djangosaml2.tests" does not define a "nonexisting_function" attribute/class' ):
7778 get_config ('djangosaml2.tests.nonexisting_function' )
7879
80+ @override_settings (LOGIN_REDIRECT_URL = '/accounts/profile/' )
81+ def test_get_fallback_login_redirect_url (self ):
82+ self .assertEqual (get_fallback_login_redirect_url (), '/accounts/profile/' )
83+
84+ with override_settings ():
85+ del settings .LOGIN_REDIRECT_URL
86+ # Neither LOGIN_REDIRECT_URL nor ACS_DEFAULT_REDIRECT_URL is configured
87+ self .assertEqual (get_fallback_login_redirect_url (), '/' )
88+
89+ with override_settings (ACS_DEFAULT_REDIRECT_URL = 'testprofiles:dashboard' ):
90+ # ACS_DEFAULT_REDIRECT_URL is configured, so it is used (and resolved)
91+ self .assertEqual (get_fallback_login_redirect_url (), '/dashboard/' )
92+
93+ with override_settings (ACS_DEFAULT_REDIRECT_URL = reverse_lazy ('testprofiles:dashboard' )):
94+ # Lazy urls are resolved
95+ self .assertEqual (get_fallback_login_redirect_url (), '/dashboard/' )
96+
7997
8098class SAML2Tests (TestCase ):
8199
@@ -158,7 +176,7 @@ def test_unsigned_post_authn_request(self):
158176 def test_login_evil_redirect (self ):
159177 """
160178 Make sure that if we give an URL other than our own host as the next
161- parameter, it is replaced with the default LOGIN_REDIRECT_URL .
179+ parameter, it is replaced with the fallback login redirect url .
162180 """
163181
164182 # monkey patch SAML configuration
@@ -178,10 +196,19 @@ def test_login_evil_redirect(self):
178196
179197 self .assertEqual (params ['RelayState' ], ['/dashboard/' ])
180198
199+ with self .subTest (ACS_DEFAULT_REDIRECT_URL = redirect_url ):
200+ with override_settings (ACS_DEFAULT_REDIRECT_URL = redirect_url ):
201+ response = self .client .get (
202+ reverse ('saml2_login' ) + '?next=http://evil.com' )
203+ url = urlparse (response ['Location' ])
204+ params = parse_qs (url .query )
205+
206+ self .assertEqual (params ['RelayState' ], ['/dashboard/' ])
207+
181208 def test_no_redirect (self ):
182209 """
183210 Make sure that if we give an empty path as the next parameter,
184- it is replaced with the default LOGIN_REDIRECT_URL .
211+ it is replaced with the fallback login redirect url .
185212 """
186213
187214 # monkey patch SAML configuration
@@ -200,6 +227,14 @@ def test_no_redirect(self):
200227
201228 self .assertEqual (params ['RelayState' ], ['/dashboard/' ])
202229
230+ with self .subTest (ACS_DEFAULT_REDIRECT_URL = redirect_url ):
231+ with override_settings (ACS_DEFAULT_REDIRECT_URL = redirect_url ):
232+ response = self .client .get (reverse ('saml2_login' ) + '?next=' )
233+ url = urlparse (response ['Location' ])
234+ params = parse_qs (url .query )
235+
236+ self .assertEqual (params ['RelayState' ], ['/dashboard/' ])
237+
203238 @override_settings (SAML_IGNORE_AUTHENTICATED_USERS_ON_LOGIN = True )
204239 def test_login_already_logged (self ):
205240 self .client .force_login (User .objects .create (username = 'user' , password = 'pass' ))
@@ -215,6 +250,16 @@ def test_login_already_logged(self):
215250 response = self .client .get (reverse ('saml2_login' ) + '?next=http://evil.com' )
216251 self .assertRedirects (response , '/dashboard/' )
217252
253+ with self .subTest (ACS_DEFAULT_REDIRECT_URL = redirect_url ):
254+ with override_settings (ACS_DEFAULT_REDIRECT_URL = redirect_url ):
255+ with self .subTest ('no next url' ):
256+ response = self .client .get (reverse ('saml2_login' ))
257+ self .assertRedirects (response , '/dashboard/' )
258+
259+ with self .subTest ('evil next url' ):
260+ response = self .client .get (reverse ('saml2_login' ) + '?next=http://evil.com' )
261+ self .assertRedirects (response , '/dashboard/' )
262+
218263 def test_unknown_idp (self ):
219264 # monkey patch SAML configuration
220265 settings .SAML_CONFIG = conf .create_conf (
@@ -300,7 +345,7 @@ def test_login_several_idps(self):
300345 self .assertIn ('AuthnRequest xmlns' , decode_base64_and_inflate (
301346 saml_request ).decode ('utf-8' ))
302347
303- @override_settings (LOGIN_REDIRECT_URL = 'testprofiles:dashboard' )
348+ @override_settings (ACS_DEFAULT_REDIRECT_URL = 'testprofiles:dashboard' )
304349 def test_assertion_consumer_service (self ):
305350 # Get initial number of users
306351 initial_user_count = User .objects .count ()
@@ -350,11 +395,11 @@ def test_assertion_consumer_service(self):
350395 'RelayState' : came_from ,
351396 })
352397
353- # as the RelayState is empty we have redirect to LOGIN_REDIRECT_URL
398+ # as the RelayState is empty we have redirect to ACS_DEFAULT_REDIRECT_URL
354399 self .assertRedirects (response , '/dashboard/' )
355400 self .assertEqual (force_text (new_user .id ), client .session [SESSION_KEY ])
356401
357- @override_settings (LOGIN_REDIRECT_URL = 'testprofiles:dashboard' )
402+ @override_settings (ACS_DEFAULT_REDIRECT_URL = 'testprofiles:dashboard' )
358403 def test_assertion_consumer_service_default_relay_state (self ):
359404 settings .SAML_CONFIG = conf .create_conf (
360405 sp_host = 'sp.example.com' ,
@@ -375,7 +420,7 @@ def test_assertion_consumer_service_default_relay_state(self):
375420 })
376421 self .assertEqual (response .status_code , 302 )
377422
378- # The RelayState is missing, redirect to LOGIN_REDIRECT_URL
423+ # The RelayState is missing, redirect to ACS_DEFAULT_REDIRECT_URL
379424 self .assertRedirects (response , '/dashboard/' )
380425 self .assertEqual (force_text (new_user .id ), self .client .session [SESSION_KEY ])
381426
0 commit comments