Merge pull request #3975 from alphagov/redirect

follow sign_in redirect even if you're already signed in
This commit is contained in:
Leo Hemsted
2021-08-17 14:58:12 +01:00
committed by GitHub
3 changed files with 29 additions and 4 deletions

View File

@@ -15,17 +15,20 @@ from app.main import main
from app.main.forms import LoginForm
from app.models.user import InvitedUser, User
from app.utils import hide_from_search_engines
from app.utils.login import is_safe_redirect_url
@main.route('/sign-in', methods=(['GET', 'POST']))
@hide_from_search_engines
def sign_in():
redirect_url = request.args.get('next')
if current_user and current_user.is_authenticated:
if redirect_url and is_safe_redirect_url(redirect_url):
return redirect(redirect_url)
return redirect(url_for('main.show_accounts_or_dashboard'))
form = LoginForm()
password_reset_url = url_for('.forgot_password', next=request.args.get('next'))
redirect_url = request.args.get('next')
if form.validate_on_submit():

View File

@@ -36,7 +36,7 @@ def log_in_user(user_id):
def redirect_when_logged_in(platform_admin):
next_url = request.args.get('next')
if next_url and _is_safe_redirect_url(next_url):
if next_url and is_safe_redirect_url(next_url):
return redirect(next_url)
return redirect(url_for('main.show_accounts_or_dashboard'))
@@ -46,8 +46,8 @@ def email_needs_revalidating(user):
return not is_less_than_days_ago(user.email_access_validated_at, 90)
# see http://flask.pocoo.org/snippets/62/
def _is_safe_redirect_url(target):
# see https://stackoverflow.com/questions/60532973/how-do-i-get-a-is-safe-url-function-to-use-with-flask-and-how-does-it-work # noqa
def is_safe_redirect_url(target):
from urllib.parse import urljoin, urlparse
host_url = urlparse(request.host_url)
redirect_url = urlparse(urljoin(request.host_url, target))

View File

@@ -105,6 +105,28 @@ def test_logged_in_user_redirects_to_account(
)
def test_logged_in_user_redirects_to_next_url(
client_request
):
client_request.get(
'main.sign_in',
next='/user-profile',
_expected_status=302,
_expected_redirect=url_for('main.user_profile', _external=True),
)
def test_logged_in_user_doesnt_do_evil_redirect(
client_request
):
client_request.get(
'main.sign_in',
next='http://www.evil.com',
_expected_status=302,
_expected_redirect=url_for('main.show_accounts_or_dashboard', _external=True),
)
@pytest.mark.parametrize('redirect_url', [
None,
f'/services/{SERVICE_ONE_ID}/templates',