WebAuthn biometric UI: login button + device management in settings
- Login page: "Face ID / Otisk prstu" button with full WebAuthn flow (auth options → navigator.credentials.get → verify → JWT) Remembers last biometric email in localStorage - Settings page: Biometric device management section (list registered devices, add new via navigator.credentials.create, remove) Auto-detects device type (Face ID, Touch ID, Android fingerprint, Windows Hello) - API: Added POST /webauthn/auth/verify endpoint returning JWT token Updated auth/options to accept email (no login required for biometric) - API client: Added 6 WebAuthn helper functions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,39 @@ export function getMe(token: string) {
|
||||
return apiFetch<{ user: User }>("/api/v1/auth/me", { token });
|
||||
}
|
||||
|
||||
// WebAuthn
|
||||
export function webauthnRegisterOptions(token: string, userId: string) {
|
||||
return apiFetch<{ data: Record<string, unknown> }>("/api/v1/webauthn/register/options", {
|
||||
method: "POST", token, body: { user_id: userId },
|
||||
});
|
||||
}
|
||||
|
||||
export function webauthnRegisterVerify(token: string, data: { user_id: string; credential_id: string; public_key: string; device_name: string }) {
|
||||
return apiFetch<{ data: Record<string, unknown>; status: string }>("/api/v1/webauthn/register/verify", {
|
||||
method: "POST", token, body: data,
|
||||
});
|
||||
}
|
||||
|
||||
export function webauthnAuthOptions(email: string) {
|
||||
return apiFetch<{ data: Record<string, unknown> }>("/api/v1/webauthn/auth/options", {
|
||||
method: "POST", body: { email },
|
||||
});
|
||||
}
|
||||
|
||||
export function webauthnAuthVerify(credentialId: string) {
|
||||
return apiFetch<{ data: { token: string; user: User } }>("/api/v1/webauthn/auth/verify", {
|
||||
method: "POST", body: { credential_id: credentialId },
|
||||
});
|
||||
}
|
||||
|
||||
export function webauthnGetDevices(token: string, userId: string) {
|
||||
return apiFetch<{ data: Array<{ id: string; device_name: string; created_at: string }> }>(`/api/v1/webauthn/devices/${userId}`, { token });
|
||||
}
|
||||
|
||||
export function webauthnDeleteDevice(token: string, deviceId: string) {
|
||||
return apiFetch<{ status: string }>(`/api/v1/webauthn/devices/${deviceId}`, { method: "DELETE", token });
|
||||
}
|
||||
|
||||
// Tasks
|
||||
export function getTasks(token: string, params?: Record<string, string>) {
|
||||
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
||||
|
||||
Reference in New Issue
Block a user