From 1ca661605d3ccb2b92cbc322c70f9b3f17685734 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Fri, 30 Sep 2022 00:46:05 +0200 Subject: [PATCH 2/8] views: improve handling of next_url for sp initiated logout (#69740) --- mellon/views.py | 14 ++++++++------ tests/test_sso_slo.py | 6 ++++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/mellon/views.py b/mellon/views.py index dd6a692..04244cd 100644 --- a/mellon/views.py +++ b/mellon/views.py @@ -723,8 +723,12 @@ class LogoutView(ProfileMixin, LogMixin, View): def sp_logout_request(self, request): '''Launch a logout request to the identity provider''' - next_url = request.GET.get(REDIRECT_FIELD_NAME) referer = request.headers.get('Referer') + field_next_url = request.GET.get(REDIRECT_FIELD_NAME) + next_url = None + if field_next_url and utils.same_origin(request.build_absolute_uri(), field_next_url): + next_url = field_next_url + next_url = next_url or '/' if not referer or utils.same_origin(request.build_absolute_uri(), referer): if hasattr(request, 'user') and request.user.is_authenticated: logout = None @@ -754,12 +758,12 @@ class LogoutView(ProfileMixin, LogMixin, View): self.log.info('user logged out, SLO request sent to IdP') else: # anonymous user: if next_url is None redirect to referer - return HttpResponseRedirect(next_url or referer) + return HttpResponseRedirect(next_url) else: self.log.warning('logout refused referer %r is not of the same origin', referer) return HttpResponseRedirect(next_url) - def sp_logout_response(self, request): + def sp_logout_response(self, request, next_url='/'): '''Launch a logout request to the identity provider''' self.profile = logout = utils.create_logout(request) logout.msgRelayState = request.GET.get('RelayState') @@ -774,9 +778,7 @@ class LogoutView(ProfileMixin, LogMixin, View): self.log.warning('partial logout') except lasso.Error as e: self.log.warning('unable to process a logout response: %s', e) - return HttpResponseRedirect(resolve_url(settings.LOGIN_REDIRECT_URL)) - next_url = self.get_next_url(default=resolve_url(settings.LOGIN_REDIRECT_URL)) - return HttpResponseRedirect(next_url) + return HttpResponseRedirect(self.get_next_url() or next_url) logout = csrf_exempt(LogoutView.as_view()) diff --git a/tests/test_sso_slo.py b/tests/test_sso_slo.py index b01c68e..62fd99f 100644 --- a/tests/test_sso_slo.py +++ b/tests/test_sso_slo.py @@ -254,14 +254,16 @@ def test_sso_slo(db, app, idp, caplog, sp_settings): # 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' + assert urlparse.urlparse(response['Location']).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/') + response = app.get( + reverse('mellon_logout') + '?next=/some/path/', extra_environ={'HTTP_REFERER': '/other/path'} + ) assert urlparse.urlparse(response['Location']).path == '/singleLogout' url = idp.process_logout_request_redirect(response.location) response = app.get(url) -- 2.37.2