diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/routes/auth.register.tsx | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/app/routes/auth.register.tsx b/app/routes/auth.register.tsx index 75a7d7c..28d5b03 100644 --- a/app/routes/auth.register.tsx +++ b/app/routes/auth.register.tsx @@ -117,11 +117,14 @@ export default function Register() { const [token, setToken] = useState(""); const [status, setStatus] = useState<"idle" | "loading" | "error">("idle"); const [errorMsg, setErrorMsg] = useState(""); + const [step, setStep] = useState(""); async function handleRegister() { setStatus("loading"); setErrorMsg(""); + setStep(""); try { + setStep("1. options 取得中…"); const optRes = await fetch("/auth/register?intent=options", { method: "POST", headers: { "Content-Type": "application/json" }, @@ -132,17 +135,20 @@ export default function Register() { throw new Error(err.error ?? "オプション取得に失敗しました"); } const optJSON = await optRes.json(); + setStep("2. options 受信 OK → credentials.create() 呼び出し中…"); + + const userId = b64urlToBuffer(optJSON.user.id); + const challenge = b64urlToBuffer(optJSON.challenge); - // @simplewebauthn/browser を使わず WebAuthn API を直接呼ぶ const credential = await navigator.credentials.create({ publicKey: { rp: optJSON.rp, user: { - id: b64urlToBuffer(optJSON.user.id), + id: userId, name: optJSON.user.name, displayName: optJSON.user.displayName ?? optJSON.user.name, }, - challenge: b64urlToBuffer(optJSON.challenge), + challenge, pubKeyCredParams: optJSON.pubKeyCredParams, timeout: 60000, attestation: "none", @@ -154,6 +160,7 @@ export default function Register() { }) as PublicKeyCredential | null; if (!credential) throw new Error("クレデンシャルの作成に失敗しました"); + setStep("3. credential 取得 OK → サーバー送信中…"); const attestation = credential.response as AuthenticatorAttestationResponse; const regResponse: RegistrationResponseJSON = { @@ -194,7 +201,7 @@ export default function Register() { <h1>log</h1> </header> <div className="auth-box"> - <h2>パスキーを登録</h2> + <h2>パスキーを登録 [debug]</h2> <p>登録トークンを入力してパスキーを作成します。</p> <input type="password" @@ -215,8 +222,11 @@ export default function Register() { <button className="btn" onClick={handleRegister} disabled={status === "loading" || !token}> {status === "loading" ? "登録中…" : "パスキーを登録"} </button> + {step && ( + <p style={{ marginTop: ".75rem", fontSize: ".8rem", color: "#6b7280" }}>{step}</p> + )} {status === "error" && ( - <p className="error-msg" style={{ marginTop: ".75rem" }}>{errorMsg}</p> + <p className="error-msg" style={{ marginTop: ".5rem" }}>{errorMsg}</p> )} </div> </div> |
