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
+51 -1
View File
@@ -7,7 +7,8 @@ import { Label } from '@/components/ui/label'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { useState } from 'react'
import { Mail, Lock, Loader2, ArrowLeft } from 'lucide-react'
import { Mail, Lock, Loader2, ArrowLeft, Key } from 'lucide-react'
import { isPasskeySupported, authenticateWithPasskey } from '@/lib/passkeys'
export default function LoginPage() {
const [email, setEmail] = useState('')
@@ -15,6 +16,8 @@ export default function LoginPage() {
const [error, setError] = useState<string | null>(null)
const [isLoading, setIsLoading] = useState(false)
const [isGoogleLoading, setIsGoogleLoading] = useState(false)
const [isPasskeyLoading, setIsPasskeyLoading] = useState(false)
const [passkeySupported] = useState(() => isPasskeySupported())
const router = useRouter()
const handleLogin = async (e: React.FormEvent) => {
@@ -56,6 +59,33 @@ export default function LoginPage() {
}
}
const handlePasskeyLogin = async () => {
const supabase = createClient()
setIsPasskeyLoading(true)
setError(null)
try {
const credential = await authenticateWithPasskey()
if (!credential) {
throw new Error('Passkey authentication failed')
}
// For now, passkeys are registered as a factor in Supabase
// This is a placeholder - in production, you'd verify the credential server-side
console.log('[v0] Passkey authentication initiated:', credential.id)
// Since this is invite-only, users would have pre-registered their passkeys
// and we'd verify them here. For now, show success.
setError('Passkey authentication requires server-side verification setup')
} catch (error: unknown) {
const message = error instanceof Error ? error.message : 'Passkey authentication failed'
setError(message)
} finally {
setIsPasskeyLoading(false)
}
}
return (
<div className="min-h-screen bg-background flex items-center justify-center p-4">
{/* Background elements */}
@@ -89,6 +119,26 @@ export default function LoginPage() {
</p>
</div>
{/* Passkey Button */}
{passkeySupported && (
<Button
type="button"
variant="outline"
className="w-full h-12 mb-4 relative"
onClick={handlePasskeyLogin}
disabled={isPasskeyLoading}
>
{isPasskeyLoading ? (
<Loader2 className="w-5 h-5 animate-spin" />
) : (
<>
<Key className="w-5 h-5 mr-2" />
Sign in with passkey
</>
)}
</Button>
)}
{/* Google OAuth Button */}
<Button
type="button"