work-in-progress atproto PDS
typescript atproto pds atcute

fix: make webauthn forms work

mary.my.id 7fa59b39 c1991119

verified
+53 -48
+25 -25
packages/danaus/src/web/controllers/account/security/webauthn.tsx
··· 65 65 66 66 <div class="flex flex-1 items-center justify-center p-4"> 67 67 <div class="w-full max-w-120 rounded-xl bg-neutral-background-1 shadow-64"> 68 + <danaus-webauthn-register class="contents" data-options={JSON.stringify(options)}> 68 69 <form {...completeWebAuthnForm} class="contents"> 69 70 <Dialog.Body> 70 71 <Dialog.Title>Set up security key</Dialog.Title> ··· 76 77 77 78 <input {...fields.token.as('hidden', token!)} /> 78 79 79 - <danaus-webauthn-register data-options={JSON.stringify(options)}> 80 - <p 81 - data-target="webauthn-register.status" 82 - class="text-base-300 text-neutral-foreground-3" 83 - > 84 - Initializing... 85 - </p> 80 + <p 81 + data-target="webauthn-register.status" 82 + class="text-base-300 text-neutral-foreground-3" 83 + > 84 + Initializing... 85 + </p> 86 86 87 - <input 88 - {...fields.response.as('hidden', '')} 89 - data-target="webauthn-register.response" 90 - /> 87 + <input 88 + {...fields.response.as('hidden', '')} 89 + data-target="webauthn-register.response" 90 + /> 91 91 92 - <Field 93 - label="Name" 94 - hint="Give this security key a name to help you identify it" 95 - validationMessageText={fields.name.issues()?.at(0)?.message} 96 - > 97 - <Input 98 - {...fields.name.as('text')} 99 - placeholder={accountManager.generateWebAuthnName( 100 - session.did, 101 - WebAuthnCredentialType.SecurityKey, 102 - )} 103 - /> 104 - </Field> 105 - </danaus-webauthn-register> 92 + <Field 93 + label="Name" 94 + hint="Give this security key a name to help you identify it" 95 + validationMessageText={fields.name.issues()?.at(0)?.message} 96 + > 97 + <Input 98 + {...fields.name.as('text')} 99 + placeholder={accountManager.generateWebAuthnName( 100 + session.did, 101 + WebAuthnCredentialType.SecurityKey, 102 + )} 103 + /> 104 + </Field> 106 105 107 106 {generalError && ( 108 107 <p role="alert" class="text-base-300 text-status-danger-foreground-1"> ··· 122 121 </Dialog.Actions> 123 122 </Dialog.Body> 124 123 </form> 124 + </danaus-webauthn-register> 125 125 </div> 126 126 </div> 127 127 </BaseLayout>,
+22 -22
packages/danaus/src/web/controllers/verify.tsx
··· 200 200 201 201 <div class="flex flex-1 items-center justify-center p-4"> 202 202 <div class="w-full max-w-96 rounded-xl bg-neutral-background-1 p-6 shadow-16"> 203 - <form {...verifyWebAuthnForm} class="flex flex-col gap-6"> 204 - <input {...fields.challenge.as('hidden', ctx.challenge.token)} /> 205 - <input {...fields.redirect.as('hidden', ctx.redirectUrl)} /> 203 + <danaus-webauthn-authenticate class="contents" data-options={JSON.stringify(options)}> 204 + <form {...verifyWebAuthnForm} class="flex flex-col gap-6" data-target="webauthn-authenticate.form"> 205 + <input {...fields.challenge.as('hidden', ctx.challenge.token)} /> 206 + <input {...fields.redirect.as('hidden', ctx.redirectUrl)} /> 206 207 207 - <div class="flex flex-col gap-2"> 208 - <h1 class="text-base-500 font-semibold"> 209 - {ctx.isSudo ? 'Confirm your identity' : 'Two-factor authentication'} 210 - </h1> 211 - <p class="text-base-300 text-neutral-foreground-3"> 212 - Insert your security key and touch it 213 - {ctx.isSudo ? ' to continue.' : ' to verify your identity.'} 214 - </p> 215 - </div> 208 + <div class="flex flex-col gap-2"> 209 + <h1 class="text-base-500 font-semibold"> 210 + {ctx.isSudo ? 'Confirm your identity' : 'Two-factor authentication'} 211 + </h1> 212 + <p class="text-base-300 text-neutral-foreground-3"> 213 + Insert your security key and touch it 214 + {ctx.isSudo ? ' to continue.' : ' to verify your identity.'} 215 + </p> 216 + </div> 216 217 217 - <danaus-webauthn-authenticate data-options={JSON.stringify(options)}> 218 218 <input {...fields.response.as('hidden', '')} data-target="webauthn-authenticate.response" /> 219 219 220 220 <Button data-target="webauthn-authenticate.start" type="button" variant="primary"> ··· 225 225 data-target="webauthn-authenticate.status" 226 226 class="text-center text-base-300 text-neutral-foreground-3" 227 227 /> 228 - </danaus-webauthn-authenticate> 229 228 230 - <OtherMethodsMenu 231 - factor="webauthn" 232 - challenge={ctx.challenge.token} 233 - redirectUrl={ctx.redirectUrl} 234 - mfaStatus={ctx.mfaStatus} 235 - isSudo={ctx.isSudo} 236 - /> 237 - </form> 229 + <OtherMethodsMenu 230 + factor="webauthn" 231 + challenge={ctx.challenge.token} 232 + redirectUrl={ctx.redirectUrl} 233 + mfaStatus={ctx.mfaStatus} 234 + isSudo={ctx.isSudo} 235 + /> 236 + </form> 237 + </danaus-webauthn-authenticate> 238 238 </div> 239 239 </div> 240 240 </BaseLayout>,
+6 -1
packages/danaus/src/web/scripts/webauthn-authenticate.js
··· 26 26 return this.querySelector('[data-target="webauthn-authenticate.status"]'); 27 27 } 28 28 29 + /** @type {HTMLFormElement | null} */ 30 + get formElement() { 31 + return this.querySelector('[data-target="webauthn-authenticate.form"]'); 32 + } 33 + 29 34 connectedCallback() { 30 35 const optionsJson = this.dataset.options; 31 36 if (!optionsJson) { ··· 103 108 status.textContent = 'Security key verified!'; 104 109 105 110 // auto-submit the form 106 - this.closest('form')?.submit(); 111 + this.formElement?.submit(); 107 112 } catch (err) { 108 113 if (startButton) { 109 114 startButton.disabled = false;