async function login(makeAssertionOptions) { const challenge = makeAssertionOptions.challenge.replace(/-/g, "+").replace(/_/g, "/"); makeAssertionOptions.challenge = Uint8Array.from(atob(challenge), c => c.charCodeAt(0)); // fix escaping. Change this to coerce makeAssertionOptions.allowCredentials.forEach(function (listItem) { var fixedId = listItem.id.replace(/\_/g, "/").replace(/\-/g, "+"); listItem.id = Uint8Array.from(atob(fixedId), c => c.charCodeAt(0)); }); let credential; try { credential = await navigator.credentials.get({ publicKey: makeAssertionOptions }) } catch (err) { showErrorAlert(err.message ? err.message : err); return; } try { await verifyAssertionWithServer(credential); } catch (e) { showErrorAlert("Could not verify assertion", e); } } /** * Sends the credential to the FIDO2 server for assertion * @param {any} assertedCredential */ async function verifyAssertionWithServer(assertedCredential) { // Move data into Arrays incase it is super long let authData = new Uint8Array(assertedCredential.response.authenticatorData); let clientDataJSON = new Uint8Array(assertedCredential.response.clientDataJSON); let rawId = new Uint8Array(assertedCredential.rawId); let sig = new Uint8Array(assertedCredential.response.signature); const data = { id: assertedCredential.id, rawId: coerceToBase64Url(rawId), type: assertedCredential.type, extensions: assertedCredential.getClientExtensionResults(), response: { authenticatorData: coerceToBase64Url(authData), clientDataJson: coerceToBase64Url(clientDataJSON), signature: coerceToBase64Url(sig) } }; document.getElementById("Response").value = JSON.stringify(data); document.getElementById("fidoForm").submit(); } document.addEventListener('DOMContentLoaded', () => { if (detectFIDOSupport() && makeAssertionOptions) { const infoMessage = document.getElementById("info-message"); const startButton = document.getElementById("btn-start"); if (isSafari()) { startButton.addEventListener("click", ev => { login(makeAssertionOptions); infoMessage.classList.remove("d-none"); startButton.classList.add("d-none"); }); startButton.classList.remove("d-none"); } else { infoMessage.classList.remove("d-none"); login(makeAssertionOptions); } } })