ui: tfa: make webAuthn abortable and restartable

Fix two things:
* do not reject the login promise when we get the abort DOMException
  error
* safely save the original challenge string as we work on a reference
  here and avoid to convert to a UInt8 array twice to avoid an
  exception.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2021-01-27 19:40:12 +01:00
parent a11c8ab485
commit e90fdf5bed

View File

@ -380,12 +380,14 @@ Ext.define('PBS.login.TfaWindow', {
let challenge = view.challenge.webauthn; let challenge = view.challenge.webauthn;
if (typeof challenge.string !== 'string') {
// Byte array fixup, keep challenge string: // Byte array fixup, keep challenge string:
let challenge_str = challenge.publicKey.challenge; challenge.string = challenge.publicKey.challenge;
challenge.publicKey.challenge = PBS.Utils.base64url_to_bytes(challenge_str); challenge.publicKey.challenge = PBS.Utils.base64url_to_bytes(challenge.string);
for (const cred of challenge.publicKey.allowCredentials) { for (const cred of challenge.publicKey.allowCredentials) {
cred.id = PBS.Utils.base64url_to_bytes(cred.id); cred.id = PBS.Utils.base64url_to_bytes(cred.id);
} }
}
let controller = new AbortController(); let controller = new AbortController();
challenge.signal = controller.signal; challenge.signal = controller.signal;
@ -395,7 +397,12 @@ Ext.define('PBS.login.TfaWindow', {
//Promise.race( ... //Promise.race( ...
hwrsp = await navigator.credentials.get(challenge); hwrsp = await navigator.credentials.get(challenge);
} catch (error) { } catch (error) {
view.onReject(error); // we do NOT want to fail login because of canceling the challenge actively,
// in some browser that's the only way to switch over to another method as the
// disallow user input during the time the challenge is active
// checking for error.code === DOMException.ABORT_ERR only works in firefox -.-
this.getViewModel().set('canConfirm', true);
// FIXME: better handling, show some message, ...?
return; return;
} finally { } finally {
let waitingMessage = me.lookup('webAuthnWaiting'); let waitingMessage = me.lookup('webAuthnWaiting');
@ -407,7 +414,7 @@ Ext.define('PBS.login.TfaWindow', {
let response = { let response = {
id: hwrsp.id, id: hwrsp.id,
type: hwrsp.type, type: hwrsp.type,
challenge: challenge_str, challenge: challenge.string,
rawId: PBS.Utils.bytes_to_base64url(hwrsp.rawId), rawId: PBS.Utils.bytes_to_base64url(hwrsp.rawId),
response: { response: {
authenticatorData: PBS.Utils.bytes_to_base64url( authenticatorData: PBS.Utils.bytes_to_base64url(