package forms type RegisterPasskeyData struct { Address string Handle string Name string Challenge string CreationBlock string } templ RegisterPasskey(action, method string, data RegisterPasskeyData) {
@sonrProfile(data.Address, data.Name, data.Handle, data.CreationBlock)
@passkeyDropzone(data.Address, data.Handle, data.Challenge) Cancel
} templ passkeyDropzone(addr string, userHandle string, challenge string) { Register Passkey } script createPasskey(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, }, }, }; // 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 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('Passkey creation failed:', err); alert(`Failed to create passkey: ${err.message || 'Unknown error'}`); }); } templ sonrProfile(addr string, name string, handle string, creationBlock string) {

sonr-testnet-1

{ handle }

{ shortenAddress(addr) }

Block Created

#{ creationBlock }

Issued to

{ name }

} // Helper function to shorten address func shortenAddress(address string) string { if len(address) <= 20 { return address } return address[:16] + "..." + address[len(address)-4:] }