Files
notifications-admin/app/assets/javascripts/authenticateSecurityKey.js
Leo Hemsted 2c55f4d0ce hard-code html error message for errorBanner
turns out that we're only using errorBanner with a static message, and
it's also full of rich html content. This means that it's probably
better to put it in the html templates with other content, rather than
hidden away in js files if we can help it.

Since there are two places, had to dupe the error message but i think
that's fine as i don't anticipate this error message being used in
significantly more places.

making it a string is a bit gross and means we don't get nice syntax
highlighting on it, but as it needs to be passed in to a jinja macro
that's the way it has to go unfortunately.
2021-09-14 18:43:27 +01:00

80 lines
3.0 KiB
JavaScript

(function (window) {
"use strict";
window.GOVUK.Modules.AuthenticateSecurityKey = function () {
this.start = function (component) {
$(component)
.on('click', function (event) {
event.preventDefault();
// hide any existing error prompt
window.GOVUK.ErrorBanner.hideBanner();
fetch('/webauthn/authenticate')
.then(response => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.arrayBuffer();
})
.then(data => {
var options = window.CBOR.decode(data);
// triggers browser dialogue to login with authenticator
return window.navigator.credentials.get(options);
})
.then(credential => {
const currentURL = new URL(window.location.href);
// create authenticateURL from admin hostname plus /webauthn/authenticate path
const authenticateURL = new URL('/webauthn/authenticate', window.location.href);
const nextUrl = currentURL.searchParams.get('next');
if (nextUrl) {
// takes nextUrl from the query string on the current browser URL
// (which should be /two-factor-webauthn) and pass it through to
// the POST. put it in a query string so it's consistent with how
// the other login flows manage it
authenticateURL.searchParams.set('next', nextUrl);
}
return fetch(authenticateURL, {
method: 'POST',
headers: { 'X-CSRFToken': component.data('csrfToken') },
body: window.CBOR.encode({
credentialId: new Uint8Array(credential.rawId),
authenticatorData: new Uint8Array(credential.response.authenticatorData),
signature: new Uint8Array(credential.response.signature),
clientDataJSON: new Uint8Array(credential.response.clientDataJSON),
})
});
})
.then(response => {
if (response.status === 403) {
// flask will have `flash`ed an error message up
window.location.reload();
return;
}
return response.arrayBuffer()
.then(cbor => {
return Promise.resolve(window.CBOR.decode(cbor));
})
.catch(() => {
throw Error(response.statusText);
})
.then(data => {
window.location.assign(data.redirect_url);
});
})
.catch(error => {
console.error(error);
// some browsers will show an error dialogue for some
// errors; to be safe we always display an error message on the page.
window.GOVUK.ErrorBanner.showBanner();
});
});
};
};
}) (window);