From 170e728d3ab0e33f03b6a37dfc4b54605746615f Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Mon, 17 Apr 2023 13:07:24 +0200 Subject: [PATCH] misc: allow login_hint parameter in login url (#76712) --- mellon/utils.py | 10 ++++++++++ mellon/views.py | 9 ++++++--- tests/test_sso_slo.py | 9 +++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/mellon/utils.py b/mellon/utils.py index 34df3d0..21888c8 100644 --- a/mellon/utils.py +++ b/mellon/utils.py @@ -357,3 +357,13 @@ def is_slo_supported(request, issuer): server.getFirstHttpMethod(server.providers[issuer], lasso.MD_PROTOCOL_TYPE_SINGLE_LOGOUT) != lasso.HTTP_METHOD_NONE ) + + +def get_login_hints_from_request(request): + request_login_hints = request.GET.getlist('login_hint') + login_hints = [ + login_hint.strip() + for login_hint in request_login_hints + if login_hint.isascii() and login_hint.isprintable() + ] + return login_hints diff --git a/mellon/views.py b/mellon/views.py index 69f9b9c..8a3c6b4 100644 --- a/mellon/views.py +++ b/mellon/views.py @@ -591,13 +591,16 @@ class LoginView(ProfileMixin, LogMixin, View): def add_login_hints(self, idp, authn_request, request, next_url=None): login_hints = utils.get_setting(idp, 'LOGIN_HINTS', []) - hints = [] + hints = set() for login_hint in login_hints: if login_hint == 'backoffice': if next_url and self.is_in_backoffice(request, next_url): - hints.append('backoffice') + hints.add('backoffice') if login_hint == 'always_backoffice': - hints.append('backoffice') + hints.add('backoffice') + + for login_hint in utils.get_login_hints_from_request(request): + hints.add(login_hint) for hint in hints: node = ET.Element(LOGIN_HINT) diff --git a/tests/test_sso_slo.py b/tests/test_sso_slo.py index b2b87b4..c96b5ed 100644 --- a/tests/test_sso_slo.py +++ b/tests/test_sso_slo.py @@ -922,3 +922,12 @@ def test_sso_slo_update_of_new_fields(db, app, idp, caplog, sp_settings): caplog.clear() response = app.get(url) assert len(caplog.records) == 0, 'logout failed' + + +def test_sso_slo_pass_login_hints_from_request(db, app, idp, caplog, sp_settings): + response = app.get(reverse('mellon_login') + '?next=/whatever/&login_hint=azure') + url, body, relay_state = idp.process_authn_request_redirect(response['Location']) + root = ET.fromstring(idp.request) + 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'