Browse Source

Add a way to view your 2FA backup codes

merge-requests/92/merge
Bauke 4 years ago
committed by Deimos
parent
commit
589918401a
  1. 6
      tildes/tildes/templates/intercooler/two_factor_backup_codes.jinja2
  2. 12
      tildes/tildes/templates/intercooler/two_factor_enabled.jinja2
  3. 12
      tildes/tildes/templates/macros/user.jinja2
  4. 4
      tildes/tildes/templates/settings.jinja2
  5. 24
      tildes/tildes/templates/settings_two_factor.jinja2
  6. 23
      tildes/tildes/views/api/web/user.py

6
tildes/tildes/templates/intercooler/two_factor_backup_codes.jinja2

@ -0,0 +1,6 @@
{# Copyright (c) 2020 Tildes contributors <code@tildes.net> #}
{# SPDX-License-Identifier: AGPL-3.0-or-later #}
{% from 'macros/user.jinja2' import two_factor_backup_codes with context %}
{{ two_factor_backup_codes() }}

12
tildes/tildes/templates/intercooler/two_factor_enabled.jinja2

@ -1,14 +1,8 @@
{# Copyright (c) 2018 Tildes contributors <code@tildes.net> #}
{# SPDX-License-Identifier: AGPL-3.0-or-later #}
<p>Congratulations! Two-factor authentication has been enabled.</p>
<p>These are your backup codes. In the event that you lose access to your authenticator device, you will need one of these codes to regain access to your account (or disable two-factor authentication). Each code can only be used once.</p>
{% from 'macros/user.jinja2' import two_factor_backup_codes with context %}
<p><strong class="text-warning">Make sure to write them down and store them in a safe place.</strong></p>
<p>Congratulations! Two-factor authentication has been enabled.</p>
<ol>
{% for code in backup_codes %}
<li><code>{{ code }}</code></li>
{% endfor %}
</ol>
{{ two_factor_backup_codes() }}

12
tildes/tildes/templates/macros/user.jinja2

@ -31,3 +31,15 @@
{% endif %}
</div>
{% endmacro %}
{% macro two_factor_backup_codes() %}
<p>These are your backup codes. In the event that you lose access to your authenticator device, you will need one of these codes to regain access to your account (or disable two-factor authentication). Each code can only be used once.</p>
<p><strong class="text-warning">Make sure to write them down and store them in a safe place.</strong></p>
<ol>
{% for code in backup_codes %}
<li><code>{{ code }}</code></li>
{% endfor %}
</ol>
{% endmacro %}

4
tildes/tildes/templates/settings.jinja2

@ -217,8 +217,8 @@
<a href="/settings/two_factor">Enable two-factor authentication</a>
<div class="text-small text-secondary">For extra security, you can enable two-factor authentication.</div>
{% else %}
<a href="/settings/two_factor">Disable two-factor authentication</a>
<div class="text-small text-secondary">Disabling two-factor authentication requires a code from your device or a backup code.</div>
<a href="/settings/two_factor">Two-factor authentication</a>
<div class="text-small text-secondary">View your backup codes or disable two-factor authentication.</div>
{% endif %}
</li>
</ul>

24
tildes/tildes/templates/settings_two_factor.jinja2

@ -9,7 +9,29 @@
{% block settings %}
{% if request.user.two_factor_enabled %}
<p>You already have two-factor authentication enabled. To disable it, enter a code from your authenticator device below and click the button. If you do not have access to your authenticator device, enter a backup code.</p>
<section>
<p>To view your backup codes, enter a code from your authenticator device below and click the button. If you do not have access to your authenticator device, enter a backup code.</p>
<form
name="view-two-factor-backup-codes"
autocomplete="off"
data-ic-post-to="{{ request.route_url('ic_user', username=request.user.username) }}"
data-ic-target="closest section"
>
<div class="form-group">
<label class="form-label" for="code">TOTP or backup code</label>
<input class="form-input" id="code" name="code" type="text" placeholder="Code" required>
</div>
<div class="form-buttons">
<button class="btn btn-primary" type="submit">View backup codes</button>
</div>
</form>
</section>
<div class="divider"></div>
<p>To disable two-factor authentication, enter a code from your authenticator device below and click the button. If you do not have access to your authenticator device, enter a backup code.</p>
<form
name="disable-two-factor"

23
tildes/tildes/views/api/web/user.py

@ -145,6 +145,29 @@ def post_disable_two_factor(request: Request, code: str) -> Response:
return {}
@ic_view_config(
route_name="user",
request_method="POST",
request_param="ic-trigger-name=view-two-factor-backup-codes",
renderer="two_factor_backup_codes.jinja2",
permission="change_two_factor",
)
@use_kwargs({"code": String()})
def post_view_two_factor_backup_codes(request: Request, code: str) -> Response:
"""Show the user their two-factor authentication backup codes."""
user = request.context
if not user.is_correct_two_factor_code(code):
raise HTTPUnauthorized(body="Invalid code")
# format the backup codes to be easier to read for output
backup_codes = [
separate_string(code, " ", 4) for code in user.two_factor_backup_codes
]
return {"backup_codes": backup_codes}
@ic_view_config(
route_name="user",
request_method="PATCH",

Loading…
Cancel
Save