mirror of
https://github.com/onsonr/nebula.git
synced 2025-03-10 17:29:11 +00:00
112 lines
3.7 KiB
Plaintext
112 lines
3.7 KiB
Plaintext
|
package input
|
||
|
|
||
|
templ PasskeyInitial(addr string, userHandle string, challenge string) {
|
||
|
<sl-button style="width: 100%;" onclick={ navigatorCredentialsCreate(addr, userHandle, challenge) }>
|
||
|
<sl-icon slot="prefix" name="passkey" library="sonr" style="font-size: 24px;" class="text-neutral-500"></sl-icon>
|
||
|
Register Passkey
|
||
|
</sl-button>
|
||
|
}
|
||
|
|
||
|
templ PasskeyError(addr string, userHandle string, challenge string) {
|
||
|
<sl-button style="width: 100%;" onclick={ navigatorCredentialsCreate(addr, userHandle, challenge) }>
|
||
|
<sl-icon slot="prefix" name="passkey" library="sonr" style="font-size: 24px;" class="text-red-500"></sl-icon>
|
||
|
Register Passkey
|
||
|
</sl-button>
|
||
|
}
|
||
|
|
||
|
templ PasskeySuccess(addr string, userHandle string, challenge string) {
|
||
|
<sl-button style="width: 100%;" onclick={ navigatorCredentialsCreate(addr, userHandle, challenge) }>
|
||
|
<sl-icon slot="prefix" name="passkey" library="sonr" style="font-size: 24px;" class="text-green-500"></sl-icon>
|
||
|
Register Passkey
|
||
|
</sl-button>
|
||
|
}
|
||
|
|
||
|
script navigatorCredentialsCreate(userId string, userHandle string, challenge string) {
|
||
|
const publicKey = {
|
||
|
challenge: Uint8Array.from(challenge, (c) => c.charCodeAt(0)),
|
||
|
rp: {
|
||
|
name: "Sonr.ID",
|
||
|
},
|
||
|
user: {
|
||
|
// Assuming that userId is ASCII-only
|
||
|
id: Uint8Array.from(userId, (c) => c.charCodeAt(0)),
|
||
|
name: userId,
|
||
|
displayName: userHandle,
|
||
|
},
|
||
|
pubKeyCredParams: [
|
||
|
{
|
||
|
type: "public-key",
|
||
|
alg: -7, // "ES256"
|
||
|
},
|
||
|
{
|
||
|
type: "public-key",
|
||
|
alg: -257, // "RS256"
|
||
|
},
|
||
|
],
|
||
|
authenticatorSelection: {
|
||
|
userVerification: "required",
|
||
|
residentKey: "required",
|
||
|
authenticatorAttachment: "platform",
|
||
|
},
|
||
|
timeout: 60000, // 1 minute
|
||
|
extensions: {
|
||
|
payment: {
|
||
|
isPayment: true,
|
||
|
},
|
||
|
largeBlob: {
|
||
|
supported: "preferred",
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
// 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) => {
|
||
|
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 || null,
|
||
|
transports: Array.isArray(response.getTransports) ? response.getTransports() : [],
|
||
|
clientExtensionResults: newCredentialInfo.getClientExtensionResults(),
|
||
|
response: {
|
||
|
attestationObject: arrayBufferToBase64URL(response.attestationObject),
|
||
|
clientDataJSON: arrayBufferToBase64URL(response.clientDataJSON)
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Set the form value with the stringified credential data
|
||
|
const credential = document.getElementById('credential-data');
|
||
|
credential.value = JSON.stringify(credentialJSON);
|
||
|
|
||
|
// Submit the form
|
||
|
const form = document.getElementById('passkey-form');
|
||
|
form.submit();
|
||
|
})
|
||
|
.catch((err) => {
|
||
|
console.error('Passkey creation failed:', err);
|
||
|
alert(`Failed to create passkey: ${err.message || 'Unknown error'}`);
|
||
|
});
|
||
|
}
|