views: keep next_url trough sp logout (#61431)

* first, create relaystate before build logout.msgUrl
* second, retrieve it in sp_logout_response
This commit is contained in:
Benjamin Dauvergne 2022-02-04 13:00:55 +01:00
parent a2019a930c
commit 947c355baf
2 changed files with 26 additions and 0 deletions

View File

@ -723,6 +723,7 @@ class LogoutView(ProfileMixin, LogMixin, View):
issuer = request.session.get('mellon_session', {}).get('issuer')
if issuer:
self.profile = logout = utils.create_logout(request)
self.get_relay_state(create=True)
try:
if 'lasso_session_dump' in request.session:
logout.setSessionFromDump(request.session['lasso_session_dump'])
@ -752,6 +753,7 @@ class LogoutView(ProfileMixin, LogMixin, View):
def sp_logout_response(self, request):
'''Launch a logout request to the identity provider'''
self.profile = logout = utils.create_logout(request)
logout.msgRelayState = request.GET.get('RelayState')
# the user shouldn't be logged anymore at this point but it may happen
# that a concurrent SSO happened in the meantime, so we do another
# logout to make sure.

View File

@ -213,6 +213,15 @@ class MockIdp:
else:
logout.processResponseMsg(force_str(url.split('?', 1)[-1]))
def process_logout_request_redirect(self, url):
logout = lasso.Logout(self.server)
logout.setIdentityFromDump(self.identity_dump)
logout.setSessionFromDump(self.session_dump)
logout.processRequestMsg(url.split('?', 1)[1])
logout.validateRequest()
logout.buildResponseMsg()
return logout.msgUrl
def mock_artifact_resolver(self):
@all_requests
def f(url, request):
@ -239,11 +248,26 @@ def test_sso_slo(db, app, idp, caplog, sp_settings):
assert urlparse.urlparse(response['Location']).path == '/whatever/'
response = app.get(reverse('mellon_logout'), extra_environ={'HTTP_REFERER': '/some/path'})
assert urlparse.urlparse(response['Location']).path == '/singleLogout'
url = idp.process_logout_request_redirect(response.location)
response = app.get(url)
assert response.location == '/'
# again, user is already logged out
response = app.get(reverse('mellon_logout'), extra_environ={'HTTP_REFERER': '/some/path'})
assert urlparse.urlparse(response['Location']).path == '/some/path'
def test_sso_slo_next(db, app, idp, caplog, sp_settings):
response = app.get(reverse('mellon_login'))
url, body, relay_state = idp.process_authn_request_redirect(response['Location'])
response = app.post(reverse('mellon_login'), params={'SAMLResponse': body, 'RelayState': relay_state})
response = app.get(reverse('mellon_logout') + '?next=/some/path/')
assert urlparse.urlparse(response['Location']).path == '/singleLogout'
url = idp.process_logout_request_redirect(response.location)
response = app.get(url)
assert response.location == '/some/path/'
def test_sso_idp_slo(db, app, idp, caplog, sp_settings):
assert Session.objects.count() == 0
assert User.objects.count() == 0