summaryrefslogtreecommitdiff
path: root/app/routes/auth.register.tsx
diff options
context:
space:
mode:
authoryyamashita <yyamashita@hetzner.yyamashita.com>2026-06-20 00:29:50 +0900
committeryyamashita <yyamashita@hetzner.yyamashita.com>2026-06-20 00:29:50 +0900
commitc205e6ad73f14db1f7efdf1e4e4b594eb73a1f34 (patch)
tree3ebf959ebaf69dc72cf05e9880a88a67052a4e7b /app/routes/auth.register.tsx
parent6de9ab5bab41ae4c2d8e06a72362cf6bf2375598 (diff)
Add step-by-step debug display to passkey registration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'app/routes/auth.register.tsx')
-rw-r--r--app/routes/auth.register.tsx20
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>