fix: WebAuthn config typo and improve error handling
Deploy Dashboard (Dev) / deploy-dev (push) Successful in 1m41s

- Fix WEBAUTHN_ORIGIN -> WEBAUTHN_ORIGINS env var name
- Add null check for cancelled passkey creation
- Use finally block to ensure loading state is always reset
- Add console.error for better debugging
This commit is contained in:
Gan, Jimmy
2026-03-11 00:53:28 +08:00
parent 75cfafd388
commit 2f8a5d84dc
3 changed files with 43 additions and 11 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "")
TELEGRAM_PROXY = os.environ.get("TELEGRAM_PROXY", "") TELEGRAM_PROXY = os.environ.get("TELEGRAM_PROXY", "")
WEBAUTHN_RP_ID = os.environ.get("WEBAUTHN_RP_ID", "nas.jimmygan.com") WEBAUTHN_RP_ID = os.environ.get("WEBAUTHN_RP_ID", "nas.jimmygan.com")
WEBAUTHN_ORIGINS = os.environ.get("WEBAUTHN_ORIGIN", "https://nas.jimmygan.com,https://nas.jimmygan.com:8443").split(",") WEBAUTHN_ORIGINS = os.environ.get("WEBAUTHN_ORIGINS", "https://nas.jimmygan.com,https://nas.jimmygan.com:8443").split(",")
# CORS # CORS
CORS_ORIGINS = os.environ.get("CORS_ORIGINS", "https://nas.jimmygan.com,https://nas.jimmygan.com:8443").split(",") CORS_ORIGINS = os.environ.get("CORS_ORIGINS", "https://nas.jimmygan.com,https://nas.jimmygan.com:8443").split(",")
+31 -4
View File
@@ -23,19 +23,46 @@ export function setRefreshToken() {}
let refreshPromise = null; let refreshPromise = null;
export async function tryRefreshSession() { function getLegacyRefreshToken() {
if (refreshPromise) return refreshPromise; return localStorage.getItem("refresh_token") || "";
refreshPromise = (async () => { }
try {
function clearLegacyRefreshToken() {
localStorage.removeItem("refresh_token");
}
async function requestRefresh(body) {
const r = await fetch(BASE + "/auth/refresh", { const r = await fetch(BASE + "/auth/refresh", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
credentials: "same-origin", credentials: "same-origin",
body: body ? JSON.stringify(body) : undefined,
}); });
if (!r.ok) return false; if (!r.ok) return false;
const data = await r.json(); const data = await r.json();
setToken(data.access_token || ""); setToken(data.access_token || "");
return !!data.access_token; return !!data.access_token;
}
export async function tryRefreshSession() {
if (refreshPromise) return refreshPromise;
refreshPromise = (async () => {
try {
const cookieRefreshed = await requestRefresh();
if (cookieRefreshed) {
clearLegacyRefreshToken();
return true;
}
const legacyRefreshToken = getLegacyRefreshToken();
if (!legacyRefreshToken) return false;
const legacyRefreshed = await requestRefresh({ refresh_token: legacyRefreshToken });
if (legacyRefreshed) {
clearLegacyRefreshToken();
return true;
}
clearLegacyRefreshToken();
return false;
} catch { } catch {
return false; return false;
} finally { } finally {
@@ -49,6 +49,9 @@
opts.excludeCredentials = opts.excludeCredentials.map(c => ({ ...c, id: base64urlToBuffer(c.id) })); opts.excludeCredentials = opts.excludeCredentials.map(c => ({ ...c, id: base64urlToBuffer(c.id) }));
} }
const cred = await navigator.credentials.create({ publicKey: opts }); const cred = await navigator.credentials.create({ publicKey: opts });
if (!cred) {
throw new Error("Passkey creation was cancelled");
}
const name = prompt("Name this passkey (e.g. MacBook, iPhone):", "Passkey") || "Passkey"; const name = prompt("Name this passkey (e.g. MacBook, iPhone):", "Passkey") || "Passkey";
const body = { const body = {
id: cred.id, id: cred.id,
@@ -64,10 +67,12 @@
passkeyMsg = "Passkey registered successfully"; passkeyMsg = "Passkey registered successfully";
await loadPasskeys(); await loadPasskeys();
} catch (e) { } catch (e) {
console.error("Passkey registration error:", e);
passkeyErr = e.body?.detail || e.message || "Failed to register passkey"; passkeyErr = e.body?.detail || e.message || "Failed to register passkey";
} } finally {
passkeyLoading = false; passkeyLoading = false;
} }
}
async function clearPasskeys() { async function clearPasskeys() {
if (!confirm("Remove all passkeys?")) return; if (!confirm("Remove all passkeys?")) return;