feat: implement passkey support with Supabase auth

Add WebAuthn utility functions and passkey manager component; update login and dashboard pages

Co-authored-by: ASOwnerYT <[email protected]>
This commit is contained in:
v0
2026-03-22 23:35:12 +00:00
co-authored by ASOwnerYT
parent da5a2e6aab
commit 1f5631552c
4 changed files with 303 additions and 24 deletions
+83
View File
@@ -0,0 +1,83 @@
'use client'
import { createClient } from '@/lib/supabase/client'
export async function registerPasskey(userId: string, displayName: string) {
const supabase = createClient()
if (!window.PublicKeyCredential) {
throw new Error('Passkeys are not supported in your browser')
}
try {
// Get registration options from Supabase
const { data, error } = await supabase.auth.signInWithEnrollFactors({
factorType: 'totp',
})
if (error) throw error
// For now, we'll use a simplified approach with browser's WebAuthn API
// Create a passkey credential
const credential = await navigator.credentials.create({
publicKey: {
challenge: new Uint8Array(32),
rp: {
name: 'Cloudrite',
id: window.location.hostname,
},
user: {
id: new TextEncoder().encode(userId),
name: userId,
displayName: displayName,
},
pubKeyCredParams: [{ type: 'public-key', alg: -7 }],
timeout: 60000,
attestation: 'direct',
},
}) as PublicKeyCredential | null
if (!credential) {
throw new Error('Failed to create passkey')
}
return credential
} catch (error) {
console.error('[v0] Passkey registration failed:', error)
throw error
}
}
export async function authenticateWithPasskey() {
if (!window.PublicKeyCredential) {
throw new Error('Passkeys are not supported in your browser')
}
try {
const assertion = await navigator.credentials.get({
publicKey: {
challenge: new Uint8Array(32),
timeout: 60000,
userVerification: 'preferred',
},
}) as PublicKeyCredential | null
if (!assertion) {
throw new Error('Passkey authentication cancelled or failed')
}
return assertion
} catch (error) {
console.error('[v0] Passkey authentication failed:', error)
throw error
}
}
export function isPasskeySupported(): boolean {
return !!(
window.PublicKeyCredential &&
navigator.credentials &&
navigator.credentials.create &&
navigator.credentials.get
)
}