27
27
from django .core .exceptions import ImproperlyConfigured
28
28
from django .test import Client , TestCase , override_settings
29
29
from django .test .client import RequestFactory
30
- from django .urls import reverse
30
+ from django .urls import reverse , reverse_lazy
31
31
from django .utils .encoding import force_text
32
32
from djangosaml2 import views
33
33
from djangosaml2 .cache import OutstandingQueriesCache
34
34
from djangosaml2 .conf import get_config
35
35
from djangosaml2 .middleware import SamlSessionMiddleware
36
36
from 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 ,
38
39
get_session_id_from_saml2 ,
39
40
get_subject_id_from_saml2 ,
40
41
saml2_from_httpredirect_request )
@@ -76,6 +77,23 @@ def test_get_config_missing_function(self):
76
77
with self .assertRaisesMessage (ImproperlyConfigured , 'Module "djangosaml2.tests" does not define a "nonexisting_function" attribute/class' ):
77
78
get_config ('djangosaml2.tests.nonexisting_function' )
78
79
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
+
79
97
80
98
class SAML2Tests (TestCase ):
81
99
@@ -158,7 +176,7 @@ def test_unsigned_post_authn_request(self):
158
176
def test_login_evil_redirect (self ):
159
177
"""
160
178
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 .
162
180
"""
163
181
164
182
# monkey patch SAML configuration
@@ -178,10 +196,19 @@ def test_login_evil_redirect(self):
178
196
179
197
self .assertEqual (params ['RelayState' ], ['/dashboard/' ])
180
198
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
+
181
208
def test_no_redirect (self ):
182
209
"""
183
210
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 .
185
212
"""
186
213
187
214
# monkey patch SAML configuration
@@ -200,6 +227,14 @@ def test_no_redirect(self):
200
227
201
228
self .assertEqual (params ['RelayState' ], ['/dashboard/' ])
202
229
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
+
203
238
@override_settings (SAML_IGNORE_AUTHENTICATED_USERS_ON_LOGIN = True )
204
239
def test_login_already_logged (self ):
205
240
self .client .force_login (User .objects .create (username = 'user' , password = 'pass' ))
@@ -215,6 +250,16 @@ def test_login_already_logged(self):
215
250
response = self .client .get (reverse ('saml2_login' ) + '?next=http://evil.com' )
216
251
self .assertRedirects (response , '/dashboard/' )
217
252
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
+
218
263
def test_unknown_idp (self ):
219
264
# monkey patch SAML configuration
220
265
settings .SAML_CONFIG = conf .create_conf (
@@ -300,7 +345,7 @@ def test_login_several_idps(self):
300
345
self .assertIn ('AuthnRequest xmlns' , decode_base64_and_inflate (
301
346
saml_request ).decode ('utf-8' ))
302
347
303
- @override_settings (LOGIN_REDIRECT_URL = 'testprofiles:dashboard' )
348
+ @override_settings (ACS_DEFAULT_REDIRECT_URL = 'testprofiles:dashboard' )
304
349
def test_assertion_consumer_service (self ):
305
350
# Get initial number of users
306
351
initial_user_count = User .objects .count ()
@@ -350,11 +395,11 @@ def test_assertion_consumer_service(self):
350
395
'RelayState' : came_from ,
351
396
})
352
397
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
354
399
self .assertRedirects (response , '/dashboard/' )
355
400
self .assertEqual (force_text (new_user .id ), client .session [SESSION_KEY ])
356
401
357
- @override_settings (LOGIN_REDIRECT_URL = 'testprofiles:dashboard' )
402
+ @override_settings (ACS_DEFAULT_REDIRECT_URL = 'testprofiles:dashboard' )
358
403
def test_assertion_consumer_service_default_relay_state (self ):
359
404
settings .SAML_CONFIG = conf .create_conf (
360
405
sp_host = 'sp.example.com' ,
@@ -375,7 +420,7 @@ def test_assertion_consumer_service_default_relay_state(self):
375
420
})
376
421
self .assertEqual (response .status_code , 302 )
377
422
378
- # The RelayState is missing, redirect to LOGIN_REDIRECT_URL
423
+ # The RelayState is missing, redirect to ACS_DEFAULT_REDIRECT_URL
379
424
self .assertRedirects (response , '/dashboard/' )
380
425
self .assertEqual (force_text (new_user .id ), self .client .session [SESSION_KEY ])
381
426
0 commit comments