fix: Improve cross-browser passkey credential handling and encoding

This commit is contained in:
Prad Nukala (aider)
2024-12-09 15:21:18 -05:00
parent bbb093b171
commit 38096db2dd
+39 -12
View File
@@ -77,27 +77,54 @@ const publicKey = {
},
},
};
// Helper function to convert ArrayBuffer to Base64URL string
function arrayBufferToBase64URL(buffer) {
const bytes = new Uint8Array(buffer);
let str = '';
bytes.forEach(byte => { str += String.fromCharCode(byte) });
return btoa(str)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
navigator.credentials
.create({ publicKey })
.then((newCredentialInfo) => {
// Convert credential to base64 string
// Convert the credential data to a proper format
const credentialJSON = JSON.stringify({
id: base64URLEncode(newCredentialInfo.rawId),
if (!(newCredentialInfo instanceof PublicKeyCredential)) {
throw new Error('Received credential is not a PublicKeyCredential');
}
const response = newCredentialInfo.response;
if (!(response instanceof AuthenticatorAttestationResponse)) {
throw new Error('Response is not an AuthenticatorAttestationResponse');
}
// Convert the credential data to a cross-platform compatible format
const credentialJSON = {
id: newCredentialInfo.id,
rawId: arrayBufferToBase64URL(newCredentialInfo.rawId),
type: newCredentialInfo.type,
authenticatorAttachment: newCredentialInfo.authenticatorAttachment,
authenticatorAttachment: newCredentialInfo.authenticatorAttachment || null,
transports: Array.isArray(response.getTransports) ? response.getTransports() : [],
clientExtensionResults: newCredentialInfo.getClientExtensionResults(),
response: {
attestationObject: base64URLEncode(newCredentialInfo.response.attestationObject),
clientDataJSON: base64URLEncode(newCredentialInfo.response.clientDataJSON)
attestationObject: arrayBufferToBase64URL(response.attestationObject),
clientDataJSON: arrayBufferToBase64URL(response.clientDataJSON)
}
});
document.getElementById('credential-data').value = btoa(credentialJSON);
document.getElementById('passkey-form').submit();
};
// Set the form value with the stringified credential data
const credentialInput = document.getElementById('credential-data');
credentialInput.value = JSON.stringify(credentialJSON);
// Submit the form
const form = document.getElementById('passkey-form');
form.submit();
})
.catch((err) => {
console.error(err);
alert('Failed to create passkey. Please try again.');
console.error('Passkey creation failed:', err);
alert(`Failed to create passkey: ${err.message || 'Unknown error'}`);
});
}