diff --git a/mellon/views.py b/mellon/views.py index 8a3c6b4..085c70f 100644 --- a/mellon/views.py +++ b/mellon/views.py @@ -26,7 +26,7 @@ import django.http import lasso import requests from django.conf import settings -from django.contrib import auth +from django.contrib import auth, messages from django.contrib.auth import REDIRECT_FIELD_NAME, get_user_model from django.core import signing from django.db import transaction @@ -785,6 +785,10 @@ class LogoutView(ProfileMixin, LogMixin, View): return HttpResponseRedirect(next_url) else: self.log.warning('logout refused referer %r is not of the same origin', referer) + messages.error( + request, + _('Logout refused, referer "{referer}" is not of the same origin.').format(referer=referer), + ) return HttpResponseRedirect(next_url) def sp_logout_response(self, request, logout_next_url='/'): diff --git a/tests/test_sso_slo.py b/tests/test_sso_slo.py index 3390dad..0caba6a 100644 --- a/tests/test_sso_slo.py +++ b/tests/test_sso_slo.py @@ -963,3 +963,29 @@ def test_sso_slo_pass_login_hints_from_request(db, app, idp, caplog, sp_settings login_hints = root.findall('.//{https://www.entrouvert.com/}login-hint') assert len(login_hints) == 1, 'missing login hint' assert login_hints[0].text == 'azure', 'login hint is not azure' + + +@pytest.fixture +def connected(db, app, idp, sp_settings): + response = app.get('/login/') + url, body, relay_state = idp.process_authn_request_redirect(response['Location']) + response = app.post( + reverse('mellon_login'), params={'SAMLResponse': body, 'RelayState': relay_state} + ).follow() + + +def test_logout_same_origin_no_referer(connected, app): + response = app.get('/logout/') + assert 'SAMLRequest' in response.location + + +def test_logout_same_origin_good_referer(connected, app): + response = app.get('/logout/', headers={'Referer': 'http://testserver/'}) + assert 'SAMLRequest' in response.location + + +def test_logout_same_origin_bad_referer(connected, app): + response = app.get('/logout/', headers={'Referer': 'http://other.example.com/'}) + assert response.location == '/' + response = response.follow() + assert 'Logout refused' in response.json['messages'] diff --git a/tests/urls_tests.py b/tests/urls_tests.py index 70377d9..d66e3e9 100644 --- a/tests/urls_tests.py +++ b/tests/urls_tests.py @@ -13,12 +13,17 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from django.http import HttpResponse +from django.contrib import messages +from django.http import JsonResponse from django.urls import include, path def homepage(request): - return HttpResponse('ok') + return JsonResponse( + { + 'messages': '\n'.join(message.message for message in messages.get_messages(request)), + } + ) urlpatterns = [