From 2c3286c28099397fe1245a07010a5930e867a4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Caune?= Date: Fri, 13 Nov 2020 16:23:28 +0200 Subject: [PATCH] Improve the "add security key" UX, require sudo mode --- hc/accounts/views.py | 2 + static/css/add_credential.css | 8 ++++ static/js/add_credential.js | 35 ++++++++++----- templates/accounts/add_credential.html | 61 ++++++++++++++++++++------ templates/base.html | 1 + 5 files changed, 81 insertions(+), 26 deletions(-) create mode 100644 static/css/add_credential.css diff --git a/hc/accounts/views.py b/hc/accounts/views.py index b55a50c3..ecb5a0aa 100644 --- a/hc/accounts/views.py +++ b/hc/accounts/views.py @@ -22,6 +22,7 @@ from fido2.server import Fido2Server from fido2.webauthn import PublicKeyCredentialRpEntity from fido2 import cbor from hc.accounts import forms +from hc.accounts.decorators import require_sudo_mode from hc.accounts.models import Credential, Profile, Project, Member from hc.api.models import Channel, Check, TokenBucket from hc.lib.date import choose_next_report_date @@ -552,6 +553,7 @@ def _verify_origin(aaa): @login_required +@require_sudo_mode def add_credential(request): rp = PublicKeyCredentialRpEntity("localhost", "Healthchecks") # FIXME use HTTPS, remove the verify_origin hack diff --git a/static/css/add_credential.css b/static/css/add_credential.css new file mode 100644 index 00000000..868070fe --- /dev/null +++ b/static/css/add_credential.css @@ -0,0 +1,8 @@ +#add-credential-waiting .spinner { + margin: 0; +} + +#add-credential-error-text { + font-family: "Lucida Console", Monaco, monospace; + margin: 16px 0; +} \ No newline at end of file diff --git a/static/js/add_credential.js b/static/js/add_credential.js index 449a38ff..c8b2e0e1 100644 --- a/static/js/add_credential.js +++ b/static/js/add_credential.js @@ -3,23 +3,34 @@ $(function() { var optionsBytes = Uint8Array.from(atob(form.dataset.options), c => c.charCodeAt(0)); // cbor.js expects ArrayBuffer as input when decoding var options = CBOR.decode(optionsBytes.buffer); - console.log("decoded options:", options); function b64(arraybuffer) { return btoa(String.fromCharCode.apply(null, new Uint8Array(arraybuffer))); } - navigator.credentials.create(options).then(function(attestation) { - console.log("got attestation: ", attestation); + function requestCredentials() { + // Hide error & success messages, show the "waiting" message + $("#name-next").addClass("hide"); + $("#add-credential-waiting").removeClass("hide"); + $("#add-credential-error").addClass("hide"); + $("#add-credential-success").addClass("hide"); - $("#attestation_object").val(b64(attestation.response.attestationObject)); - $("#client_data_json").val(b64(attestation.response.clientDataJSON)); - console.log("form updated, all is well"); + navigator.credentials.create(options).then(function(attestation) { + $("#attestation_object").val(b64(attestation.response.attestationObject)); + $("#client_data_json").val(b64(attestation.response.clientDataJSON)); + + // Show the success message and save button + $("#add-credential-waiting").addClass("hide"); + $("#add-credential-success").removeClass("hide"); + }).catch(function(err) { + // Show the error message + $("#add-credential-waiting").addClass("hide"); + $("#add-credential-error-text").text(err); + $("#add-credential-error").removeClass("hide"); + }); + } + + $("#name-next").click(requestCredentials); + $("#retry").click(requestCredentials); - $("#add-credential-submit").prop("disabled", ""); - $("#add-credential-success").removeClass("hide"); - }).catch(function(err) { - $("#add-credential-error span").text(err); - $("#add-credential-error").removeClass("hide"); - }); }); \ No newline at end of file diff --git a/templates/accounts/add_credential.html b/templates/accounts/add_credential.html index e8bb62ca..534807bb 100644 --- a/templates/accounts/add_credential.html +++ b/templates/accounts/add_credential.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{% load compress static %} +{% load compress static hc_extras %} {% block content %} @@ -11,7 +11,7 @@ data-options="{{ options }}" method="post" encrypt="multipart/form-data"> -

Add Credential

+

Add Security Key

{% csrf_token %} @@ -25,23 +25,56 @@ -
- Something went wrong. - +
+
-
- Success! - Credential acquired. +
+

Waiting for security key

+

+ Follow your browser's steps to register your security key + with {% site_name %}. +

+ +
+
+
+
+
+
+

+ Something went wrong. +

+

- +
+ +
+
+ +
+
+ Success! + Credential acquired. +
+ +
+ +
+
{% endblock %} diff --git a/templates/base.html b/templates/base.html index 7e0cb69d..c5521f2e 100644 --- a/templates/base.html +++ b/templates/base.html @@ -20,6 +20,7 @@ +