btcpayserver/BTCPayServer/wwwroot/js/webauthn/register.js
Andrew Camilleri 0554565b30
FIDO2/WebAuthN Support (#2356)
* FIDO2/WebAuthN Support

This adds initial support for WebAuthN/FIDO2 as another MFA mode. U2F is still intact and runs alongside it for now. Once this is merged, I will start work on migrating U2F support to happen over the FIDO2 protocol instead.

* Refactor and future proof system (prep work of seamless u2f migration)

* attempt js fix for mobile devices

* Apply suggestions from code review

Co-authored-by: d11n <mail@dennisreimann.de>

* fix fido name saving

* do not spam logs and hide loader when failed

* PR Changes

* Apply suggestions from code review

Co-authored-by: d11n <mail@dennisreimann.de>

* attempt fido2 bump

* add name if not named for credentials

Co-authored-by: d11n <mail@dennisreimann.de>
2021-04-20 14:06:32 +09:00

68 lines
2.4 KiB
JavaScript

if (detectFIDOSupport() && makeCredentialOptions){
register(makeCredentialOptions);
}
async function register(makeCredentialOptions) {
console.log("Credential Options Object", makeCredentialOptions);
// Turn the challenge back into the accepted format of padded base64
makeCredentialOptions.challenge = coerceToArrayBuffer(makeCredentialOptions.challenge);
// Turn ID into a UInt8Array Buffer for some reason
makeCredentialOptions.user.id = coerceToArrayBuffer(makeCredentialOptions.user.id);
makeCredentialOptions.excludeCredentials = makeCredentialOptions.excludeCredentials.map((c) => {
c.id = coerceToArrayBuffer(c.id);
return c;
});
if (makeCredentialOptions.authenticatorSelection.authenticatorAttachment == null) makeCredentialOptions.authenticatorSelection.authenticatorAttachment = undefined;
console.log("Credential Options Formatted", makeCredentialOptions);
console.log("Creating PublicKeyCredential...");
let newCredential;
try {
newCredential = await navigator.credentials.create({
publicKey: makeCredentialOptions
});
} catch (e) {
var msg = "Could not create credentials in browser. Probably because the username is already registered with your authenticator. Please change username or authenticator."
showErrorAlert(msg, e);
return;
}
console.log("PublicKeyCredential Created", newCredential);
try {
registerNewCredential(newCredential);
} catch (e) {
showErrorAlert(err.message ? err.message : err);
}
}
// This should be used to verify the auth data with the server
async function registerNewCredential(newCredential) {
// Move data into Arrays incase it is super long
let attestationObject = new Uint8Array(newCredential.response.attestationObject);
let clientDataJSON = new Uint8Array(newCredential.response.clientDataJSON);
let rawId = new Uint8Array(newCredential.rawId);
const data = {
id: newCredential.id,
rawId: coerceToBase64Url(rawId),
type: newCredential.type,
extensions: newCredential.getClientExtensionResults(),
response: {
AttestationObject: coerceToBase64Url(attestationObject),
clientDataJson: coerceToBase64Url(clientDataJSON)
}
};
document.getElementById("data").value = JSON.stringify(data);
document.getElementById("registerForm").submit();
}