diff --git a/core/admin/mailu/sso/views/base.py b/core/admin/mailu/sso/views/base.py index 0375117b..ff710add 100644 --- a/core/admin/mailu/sso/views/base.py +++ b/core/admin/mailu/sso/views/base.py @@ -8,19 +8,25 @@ import flask import flask_login import secrets import ipaddress +from urllib.parse import urlparse, urljoin +from werkzeug.urls import url_unquote @sso.route('/login', methods=['GET', 'POST']) def login(): client_ip = flask.request.headers.get('X-Real-IP', flask.request.remote_addr) form = forms.LoginForm() - form.submitAdmin.label.text = form.submitAdmin.label.text + ' Admin' - form.submitWebmail.label.text = form.submitWebmail.label.text + ' Webmail' fields = [] - if str(app.config["WEBMAIL"]).upper() != "NONE": - fields.append(form.submitWebmail) - if str(app.config["ADMIN"]).upper() != "FALSE": + + if flask.request.args.get('url'): fields.append(form.submitAdmin) + else: + form.submitAdmin.label.text = form.submitAdmin.label.text + ' Admin' + form.submitWebmail.label.text = form.submitWebmail.label.text + ' Webmail' + if str(app.config["WEBMAIL"]).upper() != "NONE": + fields.append(form.submitWebmail) + if str(app.config["ADMIN"]).upper() != "FALSE": + fields.append(form.submitAdmin) fields = [fields] if form.validate_on_submit(): @@ -28,6 +34,11 @@ def login(): destination = app.config['WEB_ADMIN'] elif form.submitWebmail.data: destination = app.config['WEB_WEBMAIL'] + if url := flask.request.args.get('url'): + url = url_unquote(url) + target = urlparse(urljoin(flask.request.url, url)) + if target.netloc == urlparse(flask.request.url).netloc: + destination = target.geturl() device_cookie, device_cookie_username = utils.limiter.parse_device_cookie(flask.request.cookies.get('rate_limit')) username = form.email.data if username != device_cookie_username and utils.limiter.should_rate_limit_ip(client_ip): @@ -57,7 +68,7 @@ def login(): def logout(): flask_login.logout_user() flask.session.destroy() - response = flask.redirect(app.config('PROXY_AUTH_LOGOUT_URL') or flask.url_for('.login')) + response = flask.redirect(app.config['PROXY_AUTH_LOGOUT_URL'] or flask.url_for('.login')) for cookie in ['roundcube_sessauth', 'roundcube_sessid', 'smsession']: response.set_cookie(cookie, 'empty', expires=0) return response diff --git a/core/admin/mailu/utils.py b/core/admin/mailu/utils.py index b432192d..bbf0a829 100644 --- a/core/admin/mailu/utils.py +++ b/core/admin/mailu/utils.py @@ -33,6 +33,7 @@ from flask.sessions import SessionMixin, SessionInterface from itsdangerous.encoding import want_bytes from werkzeug.datastructures import CallbackDict from werkzeug.middleware.proxy_fix import ProxyFix +from werkzeug.urls import url_quote # Login configuration login = flask_login.LoginManager() @@ -42,7 +43,7 @@ login.login_view = "sso.login" def handle_needs_login(): """ redirect unauthorized requests to login page """ return flask.redirect( - flask.url_for('sso.login') + flask.url_for('sso.login')+f'?url={url_quote(flask.request.url)}' ) # DNS stub configured to do DNSSEC enabled queries diff --git a/core/nginx/conf/nginx.conf b/core/nginx/conf/nginx.conf index 89eeb4bf..3c7dbc35 100644 --- a/core/nginx/conf/nginx.conf +++ b/core/nginx/conf/nginx.conf @@ -216,7 +216,7 @@ http { } location @webmail_login { - return 302 /sso/login; + return 302 /sso/login?url=$request_uri; } {% endif %} {% if ADMIN %} diff --git a/towncrier/newsfragments/2692.misc b/towncrier/newsfragments/2692.misc index 4d2937a7..c8f6f8fc 100644 --- a/towncrier/newsfragments/2692.misc +++ b/towncrier/newsfragments/2692.misc @@ -1,2 +1,2 @@ -Make the login page "guess" where the user wants to land using the Referer header +Make the login page "guess" where the user wants to land Introduce AUTH_PROXY_LOGOUT_URL to redirect users to a specific URL after they have been logged-out