From d1d134038ffa2bde66ccfafd842dcafe5eb3ea11 Mon Sep 17 00:00:00 2001 From: FreddlePat
' + lang_tfa.init_u2f + '
'); + $('#webauthn_status_auth').html('' + lang_tfa.init_u2f + '
'); $('#ConfirmTFAModal').on('shown.bs.modal', function(){ $(this).find('input[name=token]').focus(); - // If U2F - if(document.getElementById("u2f_auth_data") !== null) { - $.ajax({ - type: "GET", - cache: false, - dataType: 'script', - url: "/api/v1/get/u2f-authentication/{{ pending_mailcow_cc_username|url_encode(true)|default('null') }}", - complete: function(data){ - $('#u2f_status_auth').html(lang_tfa.waiting_usb_auth); - data; - setTimeout(function() { - console.log("Ready to authenticate"); - u2f.sign(appId, challenge, registeredKeys, function(data) { - var form = document.getElementById('u2f_auth_form'); - var auth = document.getElementById('u2f_auth_data'); - console.log("Authenticate callback", data); - auth.value = JSON.stringify(data); - form.submit(); - }); - }, 1000); - } + // If WebAuthn + if(document.getElementById("webauthn_auth_data") !== null) { + // Check Browser support + if (!window.fetch || !navigator.credentials || !navigator.credentials.create) { + window.alert('Browser not supported for WebAuthn.'); + return; + } + + window.fetch("/api/v1/get/webauthn-tfa-get-args", {method:'GET',cache:'no-cache'}).then(response => { + return response.json(); + }).then(json => { + console.log(json); + if (json.success === false) throw new Error(); + + recursiveBase64StrToArrayBuffer(json); + return json; + }).then(getCredentialArgs => { + console.log(getCredentialArgs); + return navigator.credentials.get(getCredentialArgs); + }).then(cred => { + console.log(cred); + return { + id: cred.rawId ? arrayBufferToBase64(cred.rawId) : null, + clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null, + authenticatorData: cred.response.authenticatorData ? arrayBufferToBase64(cred.response.authenticatorData) : null, + signature : cred.response.signature ? arrayBufferToBase64(cred.response.signature) : null + }; + }).then(JSON.stringify).then(function(AuthenticatorAttestationResponse) { + console.log(AuthenticatorAttestationResponse); + + var form = document.getElementById('webauthn_auth_form'); + var auth = document.getElementById('webauthn_auth_data'); + console.log("Authenticate callback", AuthenticatorAttestationResponse); + auth.value = AuthenticatorAttestationResponse; + form.submit(); + }).catch(function(err) { + if (typeof err.message === 'undefined') { + mailcow_alert_box(lang_fido2.fido2_validation_failed, "danger"); + } else { + mailcow_alert_box(lang_fido2.fido2_validation_failed + ":' + lang_tfa.init_u2f + '
'); - $.ajax({ - type: "GET", - cache: false, - dataType: 'script', - url: "/api/v1/get/u2f-registration/{{ mailcow_cc_username|url_encode(true)|default('null') }}", - complete: function(data){ - data; - setTimeout(function() { - console.log("Ready to register"); - $('#u2f_status_reg').html(lang_tfa.waiting_usb_register); - u2f.register(appId, registerRequests, registeredKeys, function(deviceResponse) { - var form = document.getElementById('u2f_reg_form'); - var reg = document.getElementById('u2f_register_data'); - console.log("Register callback: ", data); - if (deviceResponse.errorCode && deviceResponse.errorCode != 0) { - var u2f_return_code = document.getElementById('u2f_return_code'); - u2f_return_code.style.display = u2f_return_code.style.display === 'none' ? '' : null; - if (deviceResponse.errorCode == "4") { - deviceResponse.errorCode = "4 - The presented device is not eligible for this request. For a registration request this may mean that the token is already registered, and for a sign request it may mean that the token does not know the presented key handle"; - } - else if (deviceResponse.errorCode == "5") { - deviceResponse.errorCode = "5 - Timeout reached before request could be satisfied."; - } - u2f_return_code.innerHTML = lang_tfa.error_code + ': ' + deviceResponse.errorCode + ' ' + lang_tfa.reload_retry; - return; + if ($(this).val() == "webauthn") { + // check if Browser is supported + if (!window.fetch || !navigator.credentials || !navigator.credentials.create) { + window.alert('Browser not supported.'); + return; + } + + // show modal + $('#WebAuthnModal').modal('show'); + $("option:selected").prop("selected", false); + + $("#start_webauthn_register").click(() => { + var key_id = document.getElementsByName('key_id')[1].value; + + // fetch WebAuthn CreateArgs + window.fetch("/api/v1/get/webauthn-tfa-registration/{{ mailcow_cc_username|url_encode(true)|default('null') }}", {method:'GET',cache:'no-cache'}).then(response => { + return response.json(); + }).then(json => { + console.log(json); + + if (json.success === false) throw new Error(json.msg); + + recursiveBase64StrToArrayBuffer(json); + + return json; + }).then(createCredentialArgs => { + return navigator.credentials.create(createCredentialArgs); + }).then(cred => { + return { + clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null, + attestationObject: cred.response.attestationObject ? arrayBufferToBase64(cred.response.attestationObject) : null, + key_id: key_id, + tfa_method: "webauthn" + }; + }).then(JSON.stringify).then(AuthenticatorAttestationResponse => { + console.log(AuthenticatorAttestationResponse); + + return window.fetch("/api/v1/add/webauthn-tfa-registration", {method:'POST', body: AuthenticatorAttestationResponse, cache:'no-cache'}); + }).then(response => { + return response.json(); + }).then(json => { + console.log(json); + + if (json.success) { + console.log("success"); + window.location.reload(); + } else { + throw new Error(json.msg); } - reg.value = JSON.stringify(deviceResponse); - form.submit(); - }); - }, 1000); - } + }).catch(function(err) { + console.log(err); + var webauthn_return_code = document.getElementById('webauthn_return_code'); + webauthn_return_code.style.display = webauthn_return_code.style.display === 'none' ? '' : null; + webauthn_return_code.innerHTML = lang_tfa.error_code + ': ' + err + ' ' + lang_tfa.reload_retry; + }); }); - }); } if ($(this).val() == "none") { $('#DisableTFAModal').modal('show'); diff --git a/data/web/templates/modals/footer.twig b/data/web/templates/modals/footer.twig index 8e5cb175..306005a1 100644 --- a/data/web/templates/modals/footer.twig +++ b/data/web/templates/modals/footer.twig @@ -37,15 +37,15 @@' + lang_tfa.init_u2f + '
'); + $('#webauthn_status_auth').html('' + lang_tfa.init_webauthn + '
'); $('#ConfirmTFAModal').on('shown.bs.modal', function(){ $(this).find('input[name=token]').focus(); // If WebAuthn From d97a2208340ae7de116b06c28f08ffaea43e03e8 Mon Sep 17 00:00:00 2001 From: FreddlePat' + lang_tfa.init_webauthn + '
'); - $('#ConfirmTFAModal').on('shown.bs.modal', function(){ + + $('#webauthn_status_auth').html('Press to start authentication
'); + $('#start_webauthn_confirmation').click(function(){ + $('#webauthn_status_auth').html('' + lang_tfa.init_webauthn + '
'); + $(this).find('input[name=token]').focus(); // If WebAuthn if(document.getElementById("webauthn_auth_data") !== null) { From c11b6557dbd6dfa49a5038a4e5ec333903bf8594 Mon Sep 17 00:00:00 2001 From: FreddleSpl0itPress to start authentication
'); + // validate WebAuthn tfa $('#start_webauthn_confirmation').click(function(){ $('#webauthn_status_auth').html('' + lang_tfa.init_webauthn + '
'); $(this).find('input[name=token]').focus(); - // If WebAuthn if(document.getElementById("webauthn_auth_data") !== null) { // Check Browser support if (!window.fetch || !navigator.credentials || !navigator.credentials.create) { @@ -195,19 +194,18 @@ function recursiveBase64StrToArrayBuffer(obj) { return; } + // fetch webauthn auth args window.fetch("/api/v1/get/webauthn-tfa-get-args", {method:'GET',cache:'no-cache'}).then(response => { return response.json(); }).then(json => { - console.log(json); if (json.success === false) throw new Error(); recursiveBase64StrToArrayBuffer(json); return json; }).then(getCredentialArgs => { - console.log(getCredentialArgs); + // get credentials return navigator.credentials.get(getCredentialArgs); }).then(cred => { - console.log(cred); return { id: cred.rawId ? arrayBufferToBase64(cred.rawId) : null, clientDataJSON: cred.response.clientDataJSON ? arrayBufferToBase64(cred.response.clientDataJSON) : null, @@ -215,23 +213,20 @@ function recursiveBase64StrToArrayBuffer(obj) { signature : cred.response.signature ? arrayBufferToBase64(cred.response.signature) : null }; }).then(JSON.stringify).then(function(AuthenticatorAttestationResponse) { - console.log(AuthenticatorAttestationResponse); - + // send request by submit var form = document.getElementById('webauthn_auth_form'); var auth = document.getElementById('webauthn_auth_data'); - console.log("Authenticate callback", AuthenticatorAttestationResponse); auth.value = AuthenticatorAttestationResponse; form.submit(); }).catch(function(err) { - if (typeof err.message === 'undefined') { - mailcow_alert_box(lang_fido2.fido2_validation_failed, "danger"); - } else { - mailcow_alert_box(lang_fido2.fido2_validation_failed + ":{{ lang.tfa.start_webauthn_validation }}
-It seems that your Key was registered using the deprecated U2F method. We will deactivate Two-Factor-Authenticaiton for you and delete your Key.
+Please register your Key in the admin panel with the new WebAuthn method.
+ +It seems that your Key was registered using the deprecated U2F method. We will deactivate Two-Factor-Authenticaiton for you and delete your Key.
-Please register your Key in the admin panel with the new WebAuthn method.
+lang.tfa.u2f_deprecated
+lang.tfa.u2f_deprecated_important
lang.tfa.u2f_deprecated
-lang.tfa.u2f_deprecated_important
+{{ lang.tfa.u2f_deprecated }}
+{{ lang.tfa.u2f_deprecated_important }}