Add WebAuthn utility functions and passkey manager component; update login and dashboard pages Co-authored-by: ASOwnerYT <[email protected]>
84 lines
2.1 KiB
TypeScript
84 lines
2.1 KiB
TypeScript
'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
|
|
)
|
|
}
|