mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-10 10:03:21 -04:00
Merge pull request #3431 from alphagov/email-auth-interstitial
Add interstitial page before using email auth token
This commit is contained in:
@@ -28,7 +28,12 @@ def two_factor_email_sent():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@main.route('/email-auth/<token>', methods=['GET', 'POST'])
|
@main.route('/email-auth/<token>', methods=['GET'])
|
||||||
|
def two_factor_email_interstitial(token):
|
||||||
|
return render_template('views/email-link-interstitial.html')
|
||||||
|
|
||||||
|
|
||||||
|
@main.route('/email-auth/<token>', methods=['POST'])
|
||||||
def two_factor_email(token):
|
def two_factor_email(token):
|
||||||
if current_user.is_authenticated:
|
if current_user.is_authenticated:
|
||||||
return redirect_when_logged_in(platform_admin=current_user.platform_admin)
|
return redirect_when_logged_in(platform_admin=current_user.platform_admin)
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ class HeaderNavigation(Navigation):
|
|||||||
'two_factor',
|
'two_factor',
|
||||||
'two_factor_email',
|
'two_factor_email',
|
||||||
'two_factor_email_sent',
|
'two_factor_email_sent',
|
||||||
|
'two_factor_email_interstitial',
|
||||||
'verify',
|
'verify',
|
||||||
'verify_email',
|
'verify_email',
|
||||||
},
|
},
|
||||||
@@ -637,6 +638,7 @@ class MainNavigation(Navigation):
|
|||||||
'two_factor',
|
'two_factor',
|
||||||
'two_factor_email',
|
'two_factor_email',
|
||||||
'two_factor_email_sent',
|
'two_factor_email_sent',
|
||||||
|
'two_factor_email_interstitial',
|
||||||
'update_email_branding',
|
'update_email_branding',
|
||||||
'update_letter_branding',
|
'update_letter_branding',
|
||||||
'usage_for_all_services',
|
'usage_for_all_services',
|
||||||
@@ -939,6 +941,7 @@ class CaseworkNavigation(Navigation):
|
|||||||
'two_factor',
|
'two_factor',
|
||||||
'two_factor_email',
|
'two_factor_email',
|
||||||
'two_factor_email_sent',
|
'two_factor_email_sent',
|
||||||
|
'two_factor_email_interstitial',
|
||||||
'update_email_branding',
|
'update_email_branding',
|
||||||
'update_letter_branding',
|
'update_letter_branding',
|
||||||
'usage',
|
'usage',
|
||||||
@@ -1235,6 +1238,7 @@ class OrgNavigation(Navigation):
|
|||||||
'two_factor',
|
'two_factor',
|
||||||
'two_factor_email',
|
'two_factor_email',
|
||||||
'two_factor_email_sent',
|
'two_factor_email_sent',
|
||||||
|
'two_factor_email_interstitial',
|
||||||
'update_email_branding',
|
'update_email_branding',
|
||||||
'update_letter_branding',
|
'update_letter_branding',
|
||||||
'upload_contact_list',
|
'upload_contact_list',
|
||||||
|
|||||||
25
app/templates/views/email-link-interstitial.html
Normal file
25
app/templates/views/email-link-interstitial.html
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{% extends "withoutnav_template.html" %}
|
||||||
|
{% from "components/page-header.html" import page_header %}
|
||||||
|
{% from "components/page-footer.html" import page_footer %}
|
||||||
|
|
||||||
|
{% block per_page_title %}
|
||||||
|
Sign in
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block maincolumn_content %}
|
||||||
|
|
||||||
|
<div class="js-hidden">
|
||||||
|
|
||||||
|
{{ page_header('Sign in') }}
|
||||||
|
|
||||||
|
<form method="post" id="use-email-auth">
|
||||||
|
{{ page_footer('Continue to dashboard') }}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
document.getElementById("use-email-auth").submit();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -253,9 +253,48 @@ def test_two_factor_should_activate_pending_user(
|
|||||||
assert mock_activate_user.called
|
assert mock_activate_user.called
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('http_method', (
|
@pytest.mark.parametrize('extra_args, expected_encoded_next_arg', (
|
||||||
'get', 'post',
|
({}, ''),
|
||||||
|
({'next': 'https://example.com'}, '?next=https%3A%2F%2Fexample.com')
|
||||||
))
|
))
|
||||||
|
def test_valid_two_factor_email_link_shows_interstitial(
|
||||||
|
client_request,
|
||||||
|
valid_token,
|
||||||
|
mocker,
|
||||||
|
extra_args,
|
||||||
|
expected_encoded_next_arg,
|
||||||
|
):
|
||||||
|
mock_check_code = mocker.patch('app.user_api_client.check_verify_code')
|
||||||
|
encoded_token = valid_token.replace('%2E', '.')
|
||||||
|
token_url = url_for(
|
||||||
|
'main.two_factor_email_interstitial',
|
||||||
|
token=encoded_token,
|
||||||
|
**extra_args
|
||||||
|
)
|
||||||
|
|
||||||
|
# This must match the URL we put in the emails
|
||||||
|
assert token_url == f'/email-auth/{encoded_token}{expected_encoded_next_arg}'
|
||||||
|
|
||||||
|
client_request.logout()
|
||||||
|
page = client_request.get_url(token_url)
|
||||||
|
|
||||||
|
assert normalize_spaces(page.select_one('main .js-hidden').text) == (
|
||||||
|
'Sign in '
|
||||||
|
'Continue to dashboard'
|
||||||
|
)
|
||||||
|
|
||||||
|
form = page.select_one('form')
|
||||||
|
expected_form_id = 'use-email-auth'
|
||||||
|
assert 'action' not in form
|
||||||
|
assert form['method'] == 'post'
|
||||||
|
assert form['id'] == expected_form_id
|
||||||
|
assert page.select_one('main script').text.strip() == (
|
||||||
|
f'document.getElementById("{expected_form_id}").submit();'
|
||||||
|
)
|
||||||
|
|
||||||
|
assert mock_check_code.called is False
|
||||||
|
|
||||||
|
|
||||||
def test_valid_two_factor_email_link_logs_in_user(
|
def test_valid_two_factor_email_link_logs_in_user(
|
||||||
client,
|
client,
|
||||||
valid_token,
|
valid_token,
|
||||||
@@ -263,11 +302,10 @@ def test_valid_two_factor_email_link_logs_in_user(
|
|||||||
mock_get_services_with_one_service,
|
mock_get_services_with_one_service,
|
||||||
mocker,
|
mocker,
|
||||||
mock_create_event,
|
mock_create_event,
|
||||||
http_method,
|
|
||||||
):
|
):
|
||||||
mocker.patch('app.user_api_client.check_verify_code', return_value=(True, ''))
|
mocker.patch('app.user_api_client.check_verify_code', return_value=(True, ''))
|
||||||
|
|
||||||
response = getattr(client, http_method)(
|
response = client.post(
|
||||||
url_for_endpoint_with_token('main.two_factor_email', token=valid_token),
|
url_for_endpoint_with_token('main.two_factor_email', token=valid_token),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -284,7 +322,7 @@ def test_two_factor_email_link_has_expired(
|
|||||||
):
|
):
|
||||||
|
|
||||||
with set_config(app_, 'EMAIL_2FA_EXPIRY_SECONDS', -1):
|
with set_config(app_, 'EMAIL_2FA_EXPIRY_SECONDS', -1):
|
||||||
response = client.get(
|
response = client.post(
|
||||||
url_for_endpoint_with_token('main.two_factor_email', token=valid_token),
|
url_for_endpoint_with_token('main.two_factor_email', token=valid_token),
|
||||||
follow_redirects=True,
|
follow_redirects=True,
|
||||||
)
|
)
|
||||||
@@ -300,7 +338,7 @@ def test_two_factor_email_link_is_invalid(
|
|||||||
client
|
client
|
||||||
):
|
):
|
||||||
token = 12345
|
token = 12345
|
||||||
response = client.get(
|
response = client.post(
|
||||||
url_for('main.two_factor_email', token=token),
|
url_for('main.two_factor_email', token=token),
|
||||||
follow_redirects=True
|
follow_redirects=True
|
||||||
)
|
)
|
||||||
@@ -320,7 +358,7 @@ def test_two_factor_email_link_is_already_used(
|
|||||||
):
|
):
|
||||||
mocker.patch('app.user_api_client.check_verify_code', return_value=(False, 'Code has expired'))
|
mocker.patch('app.user_api_client.check_verify_code', return_value=(False, 'Code has expired'))
|
||||||
|
|
||||||
response = client.get(
|
response = client.post(
|
||||||
url_for_endpoint_with_token('main.two_factor_email', token=valid_token),
|
url_for_endpoint_with_token('main.two_factor_email', token=valid_token),
|
||||||
follow_redirects=True
|
follow_redirects=True
|
||||||
)
|
)
|
||||||
@@ -340,7 +378,7 @@ def test_two_factor_email_link_when_user_is_locked_out(
|
|||||||
):
|
):
|
||||||
mocker.patch('app.user_api_client.check_verify_code', return_value=(False, 'Code not found'))
|
mocker.patch('app.user_api_client.check_verify_code', return_value=(False, 'Code not found'))
|
||||||
|
|
||||||
response = client.get(
|
response = client.post(
|
||||||
url_for_endpoint_with_token('main.two_factor_email', token=valid_token),
|
url_for_endpoint_with_token('main.two_factor_email', token=valid_token),
|
||||||
follow_redirects=True
|
follow_redirects=True
|
||||||
)
|
)
|
||||||
@@ -356,7 +394,7 @@ def test_two_factor_email_link_used_when_user_already_logged_in(
|
|||||||
logged_in_client,
|
logged_in_client,
|
||||||
valid_token
|
valid_token
|
||||||
):
|
):
|
||||||
response = logged_in_client.get(
|
response = logged_in_client.post(
|
||||||
url_for_endpoint_with_token('main.two_factor_email', token=valid_token)
|
url_for_endpoint_with_token('main.two_factor_email', token=valid_token)
|
||||||
)
|
)
|
||||||
assert response.status_code == 302
|
assert response.status_code == 302
|
||||||
|
|||||||
Reference in New Issue
Block a user