clone

a deno framework for local-first web apps that open instantly, work offline and sync when users choose

feat(auth): let the user name their passkey at enrollment

Dami committed 94ba5fd
The account label (the passkey's name/displayName in the user's password
manager) is no longer forced to the app name. AccountGate adds a "Name this
passkey" field on the create flow; an empty value falls back to referenceApp.name.
commit
94ba5fd0c48cc6338a7e9b7d9e11dab8ade043b6
parent
3cee1f3a847284b6bf7bc903df21cd8e62807f70
author
Dami <dami.etoile@gmail.com>
3 files changed, +32 -3
Mapps/reference/src/islands/AccountGate.tsx18+++++++++++++++++-
Mapps/reference/src/styles/global.css13+++++++++++++
Mpackage/testdata/starter.snapshot.json4++--
M apps/reference/src/islands/AccountGate.tsx +17 -1
@@ -1,4 +1,5 @@
11 import { useCallback, useEffect, useState } from "preact/hooks";2+import { referenceApp } from "../app.ts";23 import { AuthError } from "../_lofi/auth.ts";34 import {45 createPasskeyAccount,
@@ -44,6 +45,9 @@ export default function AccountGate() {
4445 const [session, setSession] = useState<Session | null>(null);4546 const [busy, setBusy] = useState<"create" | "signin" | "signout" | null>(null);4647 const [error, setError] = useState<string | null>(null);48+ // The nickname the user gives their passkey — it becomes the credential's name49+ // in their password manager, so they can tell which account a key unlocks.50+ const [label, setLabel] = useState("");4751 4852 useEffect(() => {4953 let active = true;
@@ -138,11 +142,23 @@ export default function AccountGate() {
138142 Your passkey is your account. Create one, or sign in with an existing one — the same key139143 reaches the same data on every device it can.140144 </p>145+ <div class="account-field">146+ <label for="passkey-label">Name this passkey</label>147+ <input148+ id="passkey-label"149+ value={label}150+ onInput={(event) => setLabel(event.currentTarget.value)}151+ placeholder={referenceApp.name}152+ autocomplete="off"153+ disabled={busy !== null}154+ />155+ <p class="account-note">Shown in your password manager. Defaults to the app name.</p>156+ </div>141157 <div class="account-actions">142158 <button143159 type="button"144160 disabled={disabled}145- onClick={() => run("create", () => createPasskeyAccount())}161+ onClick={() => run("create", () => createPasskeyAccount(label.trim() || undefined))}146162 >147163 {busy === "create" ? "Creating…" : "Create passkey account"}148164 </button>
M apps/reference/src/styles/global.css +13 -0
M package/testdata/starter.snapshot.json +2 -2