panel/web/assets/js/dev.ts

89 lines
No EOL
3.1 KiB
TypeScript

document.addEventListener('DOMContentLoaded', () => {
// If the browser doesn't support WebAuthn, remove the register elements.
if (!window.PublicKeyCredential) {
const registerEls = document.querySelectorAll('[data-webauthn-register]');
for (const regEl of registerEls) regEl.remove();
}
document.getElementById('webAuthnRegister')?.addEventListener('submit', async (ev) => {
ev.preventDefault();
if (!window.PublicKeyCredential) {
alert('Your browser does not support WebAuthn.');
return;
}
const bgnRegisterRes = await fetch('/auth/webauthn/register');
const registerData = await bgnRegisterRes.json();
registerData.publicKey.challenge = base64ToArrayBuffer(registerData.publicKey.challenge);
registerData.publicKey.user.id = base64ToArrayBuffer(registerData.publicKey.user.id);
if (registerData.publicKey.excludeCredentials) {
for (let i = 0; i < registerData.publicKey.excludeCredentials.length; i++) {
registerData.publicKey.excludeCredentials[i].id = base64ToArrayBuffer(registerData.publicKey.excludeCredentials[i].id);
}
}
const cred = await navigator.credentials.create({
publicKey: registerData.publicKey,
})
if (!cred) {
return;
}
const form = new FormData(ev.target! as HTMLFormElement);
let name = form.get('name');
if (!name || name.length === 0) {
name = 'WebAuthn Key';
}
const credentialCreationRes = (cred as PublicKeyCredential).response as AuthenticatorAttestationResponse;
const attestationObj = credentialCreationRes.attestationObject;
const clientDataJSON = credentialCreationRes.clientDataJSON;
const rawID = (cred as PublicKeyCredential).rawId;
const fnRegisterRes = await fetch('/user/webauthn/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
id: cred.id,
name: name,
rawID: arrayBufferToBase64(rawID),
type: cred.type,
response: {
attestationObject: arrayBufferToBase64(attestationObj),
clientDataJSON: arrayBufferToBase64(clientDataJSON),
},
}),
});
if (fnRegisterRes.status != 200) {
alert('Failed to register WebAuthn key.');
return;
}
})
})
function arrayBufferToBase64(arrayBuffer: ArrayBufferLike) {
const base64String = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
return base64String.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
}
function base64ToArrayBuffer(base64: string) {
const binaryString = atob(base64.replace(/-/g, '+').replace(/_/g, '/'));
const length = binaryString.length;
const bytes = new Uint8Array(length);
for (let i = 0; i < length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}