// components/auth/next-auth-reauth-modal.tsx "use client" import * as React from "react" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import { z } from "zod" import { signIn } from "next-auth/react" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { Button } from "@/components/ui/button" import { toast } from "@/hooks/use-toast" import { AlertCircle, Shield } from "lucide-react" const reAuthSchema = z.object({ password: z.string().min(1, "Password is required"), }) type ReAuthFormValues = z.infer interface NextAuthReAuthModalProps { isOpen: boolean onSuccess: () => void userEmail: string } export function NextAuthReAuthModal({ isOpen, onSuccess, userEmail }: NextAuthReAuthModalProps) { const [isLoading, setIsLoading] = React.useState(false) const [attemptCount, setAttemptCount] = React.useState(0) const form = useForm({ resolver: zodResolver(reAuthSchema), defaultValues: { password: "", }, }) async function onSubmit(data: ReAuthFormValues) { setIsLoading(true) try { // Next-auth의 signIn 함수를 사용하여 재인증 const result = await signIn("credentials", { email: userEmail, password: data.password, redirect: false, // 리다이렉트 하지 않음 callbackUrl: undefined, }) if (result?.error) { setAttemptCount(prev => prev + 1) // 3회 이상 실패 시 추가 보안 조치 if (attemptCount >= 2) { toast({ title: "Too many failed attempts", description: "Please wait a moment before trying again.", variant: "destructive", }) // 30초 대기 setTimeout(() => { setAttemptCount(0) }, 30000) return } toast({ title: "Authentication failed", description: `Invalid password. ${2 - attemptCount} attempts remaining.`, variant: "destructive", }) form.setError("password", { type: "manual", message: "Invalid password" }) } else { // 재인증 성공 setAttemptCount(0) onSuccess() form.reset() toast({ title: "Authentication successful", description: "You can now access account settings.", }) } } catch (error) { console.error("Re-authentication error:", error) toast({ title: "Error", description: "An unexpected error occurred. Please try again.", variant: "destructive", }) } finally { setIsLoading(false) } } // 모달이 닫힐 때 폼 리셋 React.useEffect(() => { if (!isOpen) { form.reset() setAttemptCount(0) } }, [isOpen, form]) return ( {}}>
Security Verification
For your security, please confirm your password to access sensitive account settings. This verification is valid for 5 minutes.
{/* 사용자 정보 표시 */}
Signed in as: {userEmail}
{/* 경고 메시지 (실패 횟수가 많을 때) */} {attemptCount >= 2 && (

Security Alert

Multiple failed attempts detected. Please wait 30 seconds before trying again.

)} ( Current Password = 3 || isLoading} {...field} autoFocus autoComplete="current-password" /> )} />

This helps protect your account from unauthorized changes.

Your session will remain active during verification.

) }