feat(ux): ✨ allow user to name passkey at register
This commit is contained in:
parent
ee69d545b5
commit
b01bbfdb5b
|
@ -1,6 +1,6 @@
|
|||
import { startRegistration } from '@simplewebauthn/browser'
|
||||
import { PublicKeyCredentialCreationOptionsJSON } from '@simplewebauthn/types'
|
||||
import { Button } from 'univoq'
|
||||
import { Button, Input } from 'univoq'
|
||||
import type {
|
||||
WebAuthnRegisterFinishPayload,
|
||||
WebAuthnRegisterStartPayload,
|
||||
|
@ -11,40 +11,50 @@ function isWebAuthnSupported(): boolean {
|
|||
return 'credentials' in navigator
|
||||
}
|
||||
|
||||
function RegisterButton({ disabled }: { disabled?: boolean }) {
|
||||
function RegisterForm({ disabled }: { disabled?: boolean }) {
|
||||
return (
|
||||
<form onSubmit={register} method='POST' action=''>
|
||||
<Input label='Nom de la clé' name='name' required></Input>
|
||||
<Button
|
||||
label='Enregistrer une PassKey'
|
||||
variant='primary'
|
||||
onClick={register}
|
||||
disabled={disabled}
|
||||
>
|
||||
Enregistrer une PassKey
|
||||
</Button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default function PassKeyRegister() {
|
||||
if (!isWebAuthnSupported()) {
|
||||
return (
|
||||
<label>
|
||||
<div>
|
||||
<span>Erreur: WebAuthn n'est pas supporté par votre navigateur</span>
|
||||
<RegisterButton disabled />
|
||||
</label>
|
||||
<RegisterForm disabled />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<label>
|
||||
<div>
|
||||
<span>Enregistrer une PassKey pour cet appareil</span>
|
||||
<RegisterButton />
|
||||
</label>
|
||||
<RegisterForm />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
async function register() {
|
||||
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<RegisterFormFields>(form)
|
||||
|
||||
try {
|
||||
await webAuthnRegister()
|
||||
await webAuthnRegister(fields)
|
||||
} catch (cause) {
|
||||
console.error(
|
||||
new Error('passkey register failed', {
|
||||
|
@ -54,7 +64,7 @@ async function register() {
|
|||
}
|
||||
}
|
||||
|
||||
async function webAuthnRegister() {
|
||||
async function webAuthnRegister(fields: RegisterFormFields) {
|
||||
if (localStorage.getItem('webauthn-registered')) {
|
||||
return
|
||||
}
|
||||
|
@ -62,7 +72,7 @@ async function webAuthnRegister() {
|
|||
const registrationOptions = await requestApi<
|
||||
WebAuthnRegisterStartPayload,
|
||||
PublicKeyCredentialCreationOptionsJSON
|
||||
>('webauthn/register/start', 'POST')
|
||||
>('webauthn/register/start', 'POST', fields)
|
||||
|
||||
// Pass the options to the authenticator and wait for a response
|
||||
const registration = await startRegistration(registrationOptions)
|
||||
|
@ -92,3 +102,8 @@ async function webAuthnRegister() {
|
|||
console.error('Oh no, something went wrong! Response:', error)
|
||||
}
|
||||
}
|
||||
|
||||
function formJSON<T extends Record<string, unknown>>(form: HTMLFormElement): T {
|
||||
const formData = new FormData(form)
|
||||
return Object.fromEntries(formData) as unknown as T
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue