key management page

This commit is contained in:
devStorm 2020-05-18 05:07:06 -07:00
parent 6ea17b4feb
commit b64ed7ad63
No known key found for this signature in database
GPG Key ID: D52E1B66F336AC57
7 changed files with 119 additions and 77 deletions

View File

@ -13,7 +13,7 @@ from .views import (
mfa_setup,
mfa_cancel,
fido_setup,
fido_cancel,
fido_manage,
domain_detail,
lifetime_licence,
directory,

View File

@ -1,28 +0,0 @@
{% extends 'default.html' %}
{% set active_page = "setting" %}
{% block title %}
Unlink Security Key
{% endblock %}
{% block default_content %}
<div class="card">
<div class="card-body">
<h1 class="h2">Unlink Your Security Key</h1>
<p>
Please enter the password of your account so that we can ensure it's you.
</p>
<form method="post">
{{ password_check_form.csrf_token }}
<div class="font-weight-bold mt-5">Password</div>
{{ password_check_form.password(class="form-control", autofocus="true") }}
{{ render_field_errors(password_check_form.password) }}
<button class="btn btn-lg btn-danger mt-2">Unlink Key</button>
</form>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,53 @@
{% extends 'default.html' %}
{% set active_page = "setting" %}
{% block title %}
Security Key Manage
{% endblock %}
{% block head %}
<script src="{{ url_for('static', filename='node_modules/qrious/dist/qrious.min.js') }}"></script>
{% endblock %}
{% block default_content %}
<div class="card">
<div class="card-body">
<h1 class="h2">Manage Your Security Key</h1>
<p>Delete all keys will also disable WebAuthn 2FA.</p>
<form id="formManageKey" method="post">
{{ fido_manage_form.csrf_token }}
{{ fido_manage_form.credential_id(class="form-control", placeholder="") }}
</form>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Linked At</th>
<th scope="col" class="text-center">Operation</th>
</tr>
</thead>
<tbody>
{%for key in keys%}
<tr>
<th scope="row">{{ key.id }}</th>
<td>{{ key.name }}</td>
<td><script>document.write(new Date('{{ key.created_at }}').toLocaleString());</script></td>
<td class="text-center"><button class="btn btn-outline-danger" onclick="$('#credential_id').val('{{ key.credential_id }}'); $('#formManageKey').submit();">Delete</button></td>
</tr>
{%endfor%}
<tr>
<th scope="row">#</th>
<td>Link a New Key</td>
<td></td>
<td class="text-center"><a href="{{ url_for('dashboard.fido_setup') }}"><button class="btn btn-outline-success">Link</button></a></td>
</tr>
</tbody>
</table>
</div>
</div>
{% endblock %}

View File

@ -97,7 +97,7 @@
{% if current_user.fido_uuid is none %}
<a href="{{ url_for('dashboard.fido_setup') }}" class="btn btn-outline-primary">Setup WebAuthn</a>
{% else %}
<a href="{{ url_for('dashboard.fido_cancel') }}" class="btn btn-outline-danger">Disable WebAuthn</a>
<a href="{{ url_for('dashboard.fido_manage') }}" class="btn btn-outline-info">Manage WebAuthn</a>
<a href="{{ url_for('dashboard.recovery_code_route') }}" class="btn btn-outline-secondary">Recovery Codes</a>
{% endif %}
</div>

View File

@ -1,45 +0,0 @@
from flask import render_template, flash, redirect, url_for
from flask_login import login_required, current_user
from flask_wtf import FlaskForm
from wtforms import PasswordField, validators
from app.dashboard.base import dashboard_bp
from app.extensions import db
from app.models import RecoveryCode
class LoginForm(FlaskForm):
password = PasswordField("Password", validators=[validators.DataRequired()])
@dashboard_bp.route("/fido_cancel", methods=["GET", "POST"])
@login_required
def fido_cancel():
if not current_user.fido_enabled():
flash("You haven't registed a security key", "warning")
return redirect(url_for("dashboard.index"))
password_check_form = LoginForm()
if password_check_form.validate_on_submit():
password = password_check_form.password.data
if current_user.check_password(password):
current_user.fido_pk = None
current_user.fido_uuid = None
current_user.fido_sign_count = None
current_user.fido_credential_id = None
db.session.commit()
# user does not have any 2FA enabled left, delete all recovery codes
if not current_user.two_factor_authentication_enabled():
RecoveryCode.empty(current_user)
flash("We've unlinked your security key.", "success")
return redirect(url_for("dashboard.index"))
else:
flash("Incorrect password", "warning")
return render_template(
"dashboard/fido_cancel.html", password_check_form=password_check_form
)

View File

@ -0,0 +1,59 @@
from flask import render_template, flash, redirect, url_for
from flask_login import login_required, current_user
from flask_wtf import FlaskForm
from wtforms import HiddenField, validators
from app.dashboard.base import dashboard_bp
from app.extensions import db
from app.log import LOG
from app.models import RecoveryCode, FIDO
from app.dashboard.views.enter_sudo import sudo_required
class FidoManageForm(FlaskForm):
credential_id = HiddenField("credential_id", validators=[validators.DataRequired()])
@dashboard_bp.route("/fido_manage", methods=["GET", "POST"])
@login_required
@sudo_required
def fido_manage():
if not current_user.fido_enabled():
flash("You haven't registed a security key", "warning")
return redirect(url_for("dashboard.index"))
fido_manage_form = FidoManageForm()
if fido_manage_form.validate_on_submit():
credential_id = fido_manage_form.credential_id.data
fido_key = FIDO.get_by(uuid=current_user.fido_uuid, credential_id=credential_id)
if not fido_key:
flash("Unknown error, redirect back to manage page", "warning")
return redirect(url_for("dashboard.fido_manage"))
FIDO.delete(fido_key.id)
db.session.commit()
LOG.d(f"FIDO Key ID={fido_key.id} Removed")
flash(f"Key {fido_key.name} successfully unlinked", "success")
# Disable FIDO for the user if all keys have been deleted
if not FIDO.filter_by(uuid=current_user.fido_uuid).all():
current_user.fido_uuid = None
db.session.commit()
# user does not have any 2FA enabled left, delete all recovery codes
if not current_user.two_factor_authentication_enabled():
RecoveryCode.empty(current_user)
return redirect(url_for("dashboard.index"))
return redirect(url_for("dashboard.fido_manage"))
return render_template(
"dashboard/fido_manage.html",
fido_manage_form=fido_manage_form,
keys=FIDO.filter_by(uuid=current_user.fido_uuid),
)

View File

@ -13,7 +13,7 @@ from app.config import RP_ID, URL
from app.dashboard.base import dashboard_bp
from app.extensions import db
from app.log import LOG
from app.models import FIDO
from app.models import FIDO, RecoveryCode
from app.dashboard.views.enter_sudo import sudo_required
@ -84,7 +84,10 @@ def fido_setup():
)
flash("Security key has been activated", "success")
return redirect(url_for("dashboard.recovery_code_route"))
if not RecoveryCode.query.filter_by(user_id=current_user.id).all():
return redirect(url_for("dashboard.recovery_code_route"))
else:
return redirect(url_for("dashboard.fido_manage"))
# Prepare information for key registration process
fido_uuid = (