async function registerWebAuthn() {
const accessToken = localStorage.getItem('access_token');
try {
// Step 1: Begin registration
const beginResponse = await fetch(
'https://api.rcoinx.com/api/auth/webauthn/registration/begin',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
}
);
const beginData = await beginResponse.json();
const publicKeyOptions = beginData.data;
// Convert base64 strings to ArrayBuffers
publicKeyOptions.challenge = base64ToArrayBuffer(publicKeyOptions.challenge);
publicKeyOptions.user.id = base64ToArrayBuffer(publicKeyOptions.user.id);
// Step 2: Create credential using browser API
const credential = await navigator.credentials.create({
publicKey: publicKeyOptions
});
if (!credential) {
throw new Error('Failed to create credential');
}
// Step 3: Finish registration
const finishResponse = await fetch(
'https://api.rcoinx.com/api/auth/webauthn/registration/finish',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: credential.id,
rawId: arrayBufferToBase64(credential.rawId),
type: credential.type,
response: {
attestationObject: arrayBufferToBase64(
credential.response.attestationObject
),
clientDataJSON: arrayBufferToBase64(
credential.response.clientDataJSON
)
}
})
}
);
const finishData = await finishResponse.json();
if (!finishResponse.ok) {
throw new Error(finishData.message);
}
console.log('WebAuthn registration successful');
return finishData.data;
} catch (error) {
console.error('WebAuthn registration failed:', error);
throw error;
}
}
// Helper functions
function base64ToArrayBuffer(base64) {
const binaryString = window.atob(base64);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
function arrayBufferToBase64(buffer) {
const bytes = new Uint8Array(buffer);
let binary = '';
for (let i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}