91 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| {% extends "base_settings_page.html" %}
 | |
| {% block content %}
 | |
| <div style="max-width: 700px;">
 | |
| 
 | |
|     <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;" id="submitButton" />
 | |
| 
 | |
|     <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
 | |
| 		);
 | |
| 
 | |
|         const submitButton = document.getElementById("submitButton");
 | |
| 
 | |
|         async function startEnrollment() {
 | |
|             submitButton.disabled = true;
 | |
|             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!");
 | |
|             } finally {
 | |
|                 submitButton.disabled = false;
 | |
|             }
 | |
|         }
 | |
|     </script>
 | |
| 
 | |
| </div>
 | |
| 
 | |
| {% endblock content %}
 |