import { requestApi } from ':src/utils.ts' import { startRegistration } from '@simplewebauthn/browser' import { PublicKeyCredentialCreationOptionsJSON } from '@simplewebauthn/types' import { Button, Input } from 'univoq' import type { WebAuthnRegisterFinishPayload, WebAuthnRegisterStartPayload, } from '../routes/api/webauthn/register/[step].ts' function isWebAuthnSupported(): boolean { return 'credentials' in navigator } function RegisterForm({ disabled }: { disabled?: boolean }) { return (
) } export default function PassKeyRegister() { if (!isWebAuthnSupported()) { return (
Erreur: WebAuthn n'est pas supporté par votre navigateur
) } return (
Enregistrer une PassKey pour cet appareil
) } type RegisterFormFields = { name: string } async function register(event: Event) { if (!(event instanceof SubmitEvent)) return false event.preventDefault() const form = event.target as HTMLFormElement const fields = formJSON(form) try { await webAuthnRegister(fields) } catch (cause) { console.error( new Error('passkey register failed', { cause, }), ) } } async function webAuthnRegister(fields: RegisterFormFields) { if (localStorage.getItem('webauthn-registered')) { return } const registrationOptions = await requestApi< WebAuthnRegisterStartPayload, PublicKeyCredentialCreationOptionsJSON >('webauthn/register/start', 'POST', fields) // Pass the options to the authenticator and wait for a response const registration = await startRegistration(registrationOptions) .catch((error) => { // Some basic error handling if (error.name === 'InvalidStateError') { console.error( 'Authenticator was probably already registered by user', ) return null } else { throw error } }) if (registration === null) return // Verify the registration try { await requestApi< WebAuthnRegisterFinishPayload, { verified: boolean } >('webauthn/register/finish', 'POST', registration) console.log('Success!') localStorage.setItem('webauthn-registered', 'true') } catch (error) { console.error('Oh no, something went wrong! Response:', error) } } function formJSON>(form: HTMLFormElement): T { const formData = new FormData(form) return Object.fromEntries(formData) as unknown as T }