Register user security keys
This commit is contained in:
		@@ -2,11 +2,83 @@
 | 
			
		||||
{% block content %}
 | 
			
		||||
<div style="max-width: 700px;">
 | 
			
		||||
 | 
			
		||||
    <p>In order, to continue, please insert your security key & approve the registration request.</p>
 | 
			
		||||
    <p>In order to continue, please click on the "Start Enrollment" button, insert your security key and approve the
 | 
			
		||||
        registration request.</p>
 | 
			
		||||
 | 
			
		||||
    <div class="form-group">
 | 
			
		||||
        <label for="inputKeyName" class="form-label mt-4">Key name</label>
 | 
			
		||||
        <input type="text" class="form-control" id="inputKeyName"
 | 
			
		||||
               placeholder="Device / Authenticator app name"
 | 
			
		||||
               value="Security key" minlength="1" required/>
 | 
			
		||||
        <small class="form-text text-muted">Please give a name to your key to identify it more easily later.</small>
 | 
			
		||||
        <div class="invalid-feedback">Please give a name to this security key</div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <input type="button" class="btn btn-primary" value="Start enrollment" onclick="startEnrollment()"
 | 
			
		||||
           style="margin-top: 20px;"/>
 | 
			
		||||
 | 
			
		||||
    <script src="/assets/js/base64_lib.js"></script>
 | 
			
		||||
    <script>
 | 
			
		||||
        const OPAQUE_STATE = "{{ opaque_state }}";
 | 
			
		||||
        const REGISTRATION_CHALLENGE = JSON.parse(decodeURIComponent("{{ challenge_json }}"));
 | 
			
		||||
 | 
			
		||||
        // Decode data
 | 
			
		||||
        REGISTRATION_CHALLENGE.publicKey.challenge = base64NoPaddingToUint8Array(
 | 
			
		||||
			REGISTRATION_CHALLENGE.publicKey.challenge
 | 
			
		||||
		);
 | 
			
		||||
		REGISTRATION_CHALLENGE.publicKey.user.id = base64NoPaddingToUint8Array(
 | 
			
		||||
			REGISTRATION_CHALLENGE.publicKey.user.id
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        async function startEnrollment() {
 | 
			
		||||
            try {
 | 
			
		||||
                const factorNameInput = document.getElementById("inputKeyName");
 | 
			
		||||
                factorNameInput.classList.remove("is-invalid");
 | 
			
		||||
                if (factorNameInput.value.length === 0) {
 | 
			
		||||
                    factorNameInput.classList.add("is-invalid");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                const cred = await navigator.credentials.create(REGISTRATION_CHALLENGE);
 | 
			
		||||
 | 
			
		||||
                // Encode data that needs to be encoded
 | 
			
		||||
                const credential_res = {
 | 
			
		||||
                    id: cred.id,
 | 
			
		||||
                    rawId: ArrayBufferToBase64(cred.rawId),
 | 
			
		||||
                    type: cred.type,
 | 
			
		||||
                    response: {
 | 
			
		||||
                        attestationObject: ArrayBufferToBase64(
 | 
			
		||||
                            cred.response.attestationObject
 | 
			
		||||
                        ),
 | 
			
		||||
                        clientDataJSON: ArrayBufferToBase64(
 | 
			
		||||
                            cred.response.clientDataJSON
 | 
			
		||||
                        ),
 | 
			
		||||
                    },
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                const res = await fetch("/settings/api/two_factor/save_webauthn_factor", {
 | 
			
		||||
                    method: "post",
 | 
			
		||||
                    headers: {
 | 
			
		||||
                      'Content-Type': 'application/json',
 | 
			
		||||
                    },
 | 
			
		||||
                    body: JSON.stringify({
 | 
			
		||||
                        opaque_state: OPAQUE_STATE,
 | 
			
		||||
                        factor_name: factorNameInput.value,
 | 
			
		||||
                        credential: credential_res,
 | 
			
		||||
                    })
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                let text = await res.text();
 | 
			
		||||
                alert(text);
 | 
			
		||||
 | 
			
		||||
                if (res.status == 200)
 | 
			
		||||
                    location.href = "/settings/two_factors";
 | 
			
		||||
            } catch(e) {
 | 
			
		||||
                console.error(e);
 | 
			
		||||
                alert("Failed enrollment, please try again!");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    </script>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user