tangled
alpha
login
or
join now
mary.my.id
/
danaus
4
fork
atom
work-in-progress atproto PDS
typescript
atproto
pds
atcute
4
fork
atom
overview
issues
pulls
pipelines
fix: make webauthn forms work
mary.my.id
1 month ago
7fa59b39
c1991119
verified
This commit was signed with the committer's
known signature
.
mary.my.id
SSH Key Fingerprint:
SHA256:ZlTP/auFSGpGnaoDg4mCTG1g9OZvXp62jWR4c6H4O3c=
+53
-48
3 changed files
expand all
collapse all
unified
split
packages
danaus
src
web
controllers
account
security
webauthn.tsx
verify.tsx
scripts
webauthn-authenticate.js
+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
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
79
-
<danaus-webauthn-register data-options={JSON.stringify(options)}>
80
80
-
<p
81
81
-
data-target="webauthn-register.status"
82
82
-
class="text-base-300 text-neutral-foreground-3"
83
83
-
>
84
84
-
Initializing...
85
85
-
</p>
80
80
+
<p
81
81
+
data-target="webauthn-register.status"
82
82
+
class="text-base-300 text-neutral-foreground-3"
83
83
+
>
84
84
+
Initializing...
85
85
+
</p>
86
86
87
87
-
<input
88
88
-
{...fields.response.as('hidden', '')}
89
89
-
data-target="webauthn-register.response"
90
90
-
/>
87
87
+
<input
88
88
+
{...fields.response.as('hidden', '')}
89
89
+
data-target="webauthn-register.response"
90
90
+
/>
91
91
92
92
-
<Field
93
93
-
label="Name"
94
94
-
hint="Give this security key a name to help you identify it"
95
95
-
validationMessageText={fields.name.issues()?.at(0)?.message}
96
96
-
>
97
97
-
<Input
98
98
-
{...fields.name.as('text')}
99
99
-
placeholder={accountManager.generateWebAuthnName(
100
100
-
session.did,
101
101
-
WebAuthnCredentialType.SecurityKey,
102
102
-
)}
103
103
-
/>
104
104
-
</Field>
105
105
-
</danaus-webauthn-register>
92
92
+
<Field
93
93
+
label="Name"
94
94
+
hint="Give this security key a name to help you identify it"
95
95
+
validationMessageText={fields.name.issues()?.at(0)?.message}
96
96
+
>
97
97
+
<Input
98
98
+
{...fields.name.as('text')}
99
99
+
placeholder={accountManager.generateWebAuthnName(
100
100
+
session.did,
101
101
+
WebAuthnCredentialType.SecurityKey,
102
102
+
)}
103
103
+
/>
104
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
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
203
-
<form {...verifyWebAuthnForm} class="flex flex-col gap-6">
204
204
-
<input {...fields.challenge.as('hidden', ctx.challenge.token)} />
205
205
-
<input {...fields.redirect.as('hidden', ctx.redirectUrl)} />
203
203
+
<danaus-webauthn-authenticate class="contents" data-options={JSON.stringify(options)}>
204
204
+
<form {...verifyWebAuthnForm} class="flex flex-col gap-6" data-target="webauthn-authenticate.form">
205
205
+
<input {...fields.challenge.as('hidden', ctx.challenge.token)} />
206
206
+
<input {...fields.redirect.as('hidden', ctx.redirectUrl)} />
206
207
207
207
-
<div class="flex flex-col gap-2">
208
208
-
<h1 class="text-base-500 font-semibold">
209
209
-
{ctx.isSudo ? 'Confirm your identity' : 'Two-factor authentication'}
210
210
-
</h1>
211
211
-
<p class="text-base-300 text-neutral-foreground-3">
212
212
-
Insert your security key and touch it
213
213
-
{ctx.isSudo ? ' to continue.' : ' to verify your identity.'}
214
214
-
</p>
215
215
-
</div>
208
208
+
<div class="flex flex-col gap-2">
209
209
+
<h1 class="text-base-500 font-semibold">
210
210
+
{ctx.isSudo ? 'Confirm your identity' : 'Two-factor authentication'}
211
211
+
</h1>
212
212
+
<p class="text-base-300 text-neutral-foreground-3">
213
213
+
Insert your security key and touch it
214
214
+
{ctx.isSudo ? ' to continue.' : ' to verify your identity.'}
215
215
+
</p>
216
216
+
</div>
216
217
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
228
-
</danaus-webauthn-authenticate>
229
228
230
230
-
<OtherMethodsMenu
231
231
-
factor="webauthn"
232
232
-
challenge={ctx.challenge.token}
233
233
-
redirectUrl={ctx.redirectUrl}
234
234
-
mfaStatus={ctx.mfaStatus}
235
235
-
isSudo={ctx.isSudo}
236
236
-
/>
237
237
-
</form>
229
229
+
<OtherMethodsMenu
230
230
+
factor="webauthn"
231
231
+
challenge={ctx.challenge.token}
232
232
+
redirectUrl={ctx.redirectUrl}
233
233
+
mfaStatus={ctx.mfaStatus}
234
234
+
isSudo={ctx.isSudo}
235
235
+
/>
236
236
+
</form>
237
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
29
+
/** @type {HTMLFormElement | null} */
30
30
+
get formElement() {
31
31
+
return this.querySelector('[data-target="webauthn-authenticate.form"]');
32
32
+
}
33
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
106
-
this.closest('form')?.submit();
111
111
+
this.formElement?.submit();
107
112
} catch (err) {
108
113
if (startButton) {
109
114
startButton.disabled = false;