forked from GithubBackups/healthchecks
Add error handling on the client side, use Django form API
This commit is contained in:
parent
1eaa216d3a
commit
53688f1d87
@ -1,7 +1,11 @@
|
||||
import base64
|
||||
from datetime import timedelta as td
|
||||
|
||||
from django import forms
|
||||
from django.contrib.auth import authenticate
|
||||
from django.contrib.auth.models import User
|
||||
from fido2.ctap2 import AttestationObject
|
||||
from fido2.client import ClientData
|
||||
from hc.api.models import TokenBucket
|
||||
|
||||
|
||||
@ -112,3 +116,23 @@ class ProjectNameForm(forms.Form):
|
||||
|
||||
class TransferForm(forms.Form):
|
||||
email = LowercaseEmailField()
|
||||
|
||||
|
||||
class AddCredentialForm(forms.Form):
|
||||
name = forms.CharField(max_length=100, required=False)
|
||||
client_data_json = forms.CharField(required=True)
|
||||
attestation_object = forms.CharField(required=True)
|
||||
|
||||
def clean_client_data_json(self):
|
||||
v = self.cleaned_data["client_data_json"]
|
||||
binary = base64.b64decode(v.encode())
|
||||
obj = ClientData(binary)
|
||||
|
||||
return obj
|
||||
|
||||
def clean_attestation_object(self):
|
||||
v = self.cleaned_data["attestation_object"]
|
||||
binary = base64.b64decode(v.encode())
|
||||
obj = AttestationObject(binary)
|
||||
|
||||
return obj
|
||||
|
@ -18,8 +18,6 @@ from django.utils.timezone import now
|
||||
from django.urls import resolve, Resolver404
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.views.decorators.http import require_POST
|
||||
from fido2.client import ClientData
|
||||
from fido2.ctap2 import AttestationObject
|
||||
from fido2.server import Fido2Server
|
||||
from fido2.webauthn import PublicKeyCredentialRpEntity
|
||||
from fido2 import cbor
|
||||
@ -559,18 +557,15 @@ def add_credential(request):
|
||||
# FIXME use HTTPS, remove the verify_origin hack
|
||||
server = Fido2Server(rp, verify_origin=_verify_origin)
|
||||
|
||||
def decode(form, key):
|
||||
return base64.b64decode(request.POST[key].encode())
|
||||
|
||||
if request.method == "POST":
|
||||
# idea: use AddCredentialForm
|
||||
client_data = ClientData(decode(request.POST, "clientDataJSON"))
|
||||
att_obj = AttestationObject(decode(request.POST, "attestationObject"))
|
||||
print("clientData", client_data)
|
||||
print("AttestationObject:", att_obj)
|
||||
form = forms.AddCredentialForm(request.POST)
|
||||
if not form.is_valid():
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
auth_data = server.register_complete(
|
||||
request.session["state"], client_data, att_obj
|
||||
request.session["state"],
|
||||
form.cleaned_data["client_data_json"],
|
||||
form.cleaned_data["attestation_object"],
|
||||
)
|
||||
|
||||
c = Credential(user=request.user)
|
||||
@ -578,12 +573,9 @@ def add_credential(request):
|
||||
c.data = auth_data.credential_data
|
||||
c.save()
|
||||
|
||||
print("REGISTERED CREDENTIAL:", auth_data.credential_data)
|
||||
return render(request, "accounts/success.html")
|
||||
return redirect("hc-profile")
|
||||
|
||||
credentials = [c.unpack() for c in request.user.credentials.all()]
|
||||
print(credentials)
|
||||
|
||||
options, state = server.register_begin(
|
||||
{
|
||||
"id": request.user.username.encode(),
|
||||
@ -595,6 +587,5 @@ def add_credential(request):
|
||||
|
||||
request.session["state"] = state
|
||||
|
||||
# FIXME: avoid using cbor and cbor.js?
|
||||
ctx = {"options": base64.b64encode(cbor.encode(options)).decode()}
|
||||
return render(request, "accounts/add_credential.html", ctx)
|
||||
|
@ -1,8 +1,8 @@
|
||||
$(function() {
|
||||
var form = document.getElementById("add-credential-form");
|
||||
var optionsBinary = btoa(form.dataset.options);
|
||||
var array = Uint8Array.from(atob(form.dataset.options), c => c.charCodeAt(0));
|
||||
var options = CBOR.decode(array.buffer);
|
||||
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) {
|
||||
@ -12,11 +12,14 @@ $(function() {
|
||||
navigator.credentials.create(options).then(function(attestation) {
|
||||
console.log("got attestation: ", attestation);
|
||||
|
||||
document.getElementById("attestationObject").value = b64(attestation.response.attestationObject);
|
||||
document.getElementById("clientDataJSON").value = b64(attestation.response.clientDataJSON);
|
||||
$("#attestation_object").val(b64(attestation.response.attestationObject));
|
||||
$("#client_data_json").val(b64(attestation.response.clientDataJSON));
|
||||
console.log("form updated, all is well");
|
||||
|
||||
$("#add-credential-submit").prop("disabled", "");
|
||||
$("#add-credential-success").removeClass("hide");
|
||||
}).catch(function(err) {
|
||||
console.log("Something went wrong", err);
|
||||
$("#add-credential-error span").text(err);
|
||||
$("#add-credential-error").removeClass("hide");
|
||||
});
|
||||
});
|
@ -2,18 +2,20 @@
|
||||
{% load compress static %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Add Credential</h1>
|
||||
|
||||
{{ registration_dict|json_script:"registration" }}
|
||||
|
||||
<div class="row">
|
||||
<form
|
||||
id="add-credential-form"
|
||||
class="col-sm-6 col-sm-offset-3"
|
||||
data-options="{{ options }}"
|
||||
method="post"
|
||||
encrypt="multipart/form-data">
|
||||
<h1>Add Credential</h1>
|
||||
|
||||
{% csrf_token %}
|
||||
<input id="attestationObject" type="hidden" name="attestationObject">
|
||||
<input id="clientDataJSON" type="hidden" name="clientDataJSON">
|
||||
<input id="attestation_object" type="hidden" name="attestation_object">
|
||||
<input id="client_data_json" type="hidden" name="client_data_json">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
@ -23,14 +25,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="add-credential-error" class="alert alert-danger hide">
|
||||
<strong>Something went wrong.</strong>
|
||||
<span></span>
|
||||
</div>
|
||||
|
||||
<div id="add-credential-success" class="alert alert-success hide">
|
||||
<strong>Success!</strong>
|
||||
Credential acquired.
|
||||
</div>
|
||||
|
||||
|
||||
<input
|
||||
id="add-credential-submit"
|
||||
class="btn btn-default"
|
||||
class="btn btn-default pull-right"
|
||||
type="submit"
|
||||
name=""
|
||||
value="Save Credential" disabled>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
Loading…
x
Reference in New Issue
Block a user