From 3cc7f218b84a49961357f549225d3b11c16a8bc7 Mon Sep 17 00:00:00 2001 From: Hafiz N Date: Fri, 19 Jan 2024 20:41:57 +0530 Subject: [PATCH] fix: display of 2FA form after successful pw validation (#9) Ensured 2FA form is displayed only after the password has been successfully validated. --- actions/login.ts | 56 +++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/actions/login.ts b/actions/login.ts index b62c81d..a5c026f 100644 --- a/actions/login.ts +++ b/actions/login.ts @@ -1,6 +1,7 @@ "use server"; import * as z from "zod"; +import bcrypt from "bcryptjs"; import { AuthError } from "next-auth"; import { db } from "@/lib/db"; @@ -8,22 +9,17 @@ import { signIn } from "@/auth"; import { LoginSchema } from "@/schemas"; import { getUserByEmail } from "@/data/user"; import { getTwoFactorTokenByEmail } from "@/data/two-factor-token"; -import { - sendVerificationEmail, - sendTwoFactorTokenEmail, -} from "@/lib/mail"; +import { sendVerificationEmail, sendTwoFactorTokenEmail } from "@/lib/mail"; import { DEFAULT_LOGIN_REDIRECT } from "@/routes"; -import { +import { generateVerificationToken, - generateTwoFactorToken + generateTwoFactorToken, } from "@/lib/tokens"; -import { - getTwoFactorConfirmationByUserId -} from "@/data/two-factor-confirmation"; +import { getTwoFactorConfirmationByUserId } from "@/data/two-factor-confirmation"; export const login = async ( values: z.infer, - callbackUrl?: string | null, + callbackUrl?: string | null ) => { const validatedFields = LoginSchema.safeParse(values); @@ -36,27 +32,34 @@ export const login = async ( const existingUser = await getUserByEmail(email); if (!existingUser || !existingUser.email || !existingUser.password) { - return { error: "Email does not exist!" } + return { error: "Email does not exist!" }; } if (!existingUser.emailVerified) { const verificationToken = await generateVerificationToken( - existingUser.email, + existingUser.email ); await sendVerificationEmail( verificationToken.email, - verificationToken.token, + verificationToken.token ); return { success: "Confirmation email sent!" }; } if (existingUser.isTwoFactorEnabled && existingUser.email) { + const isPasswordValid = await bcrypt.compare( + password, + existingUser.password + ); + + if (!isPasswordValid) { + return { error: "Invalid credentials!" }; + } + if (code) { - const twoFactorToken = await getTwoFactorTokenByEmail( - existingUser.email - ); + const twoFactorToken = await getTwoFactorTokenByEmail(existingUser.email); if (!twoFactorToken) { return { error: "Invalid code!" }; @@ -73,7 +76,7 @@ export const login = async ( } await db.twoFactorToken.delete({ - where: { id: twoFactorToken.id } + where: { id: twoFactorToken.id }, }); const existingConfirmation = await getTwoFactorConfirmationByUserId( @@ -82,21 +85,16 @@ export const login = async ( if (existingConfirmation) { await db.twoFactorConfirmation.delete({ - where: { id: existingConfirmation.id } + where: { id: existingConfirmation.id }, }); } await db.twoFactorConfirmation.create({ - data: { - userId: existingUser.id, - } + data: { userId: existingUser.id }, }); } else { - const twoFactorToken = await generateTwoFactorToken(existingUser.email) - await sendTwoFactorTokenEmail( - twoFactorToken.email, - twoFactorToken.token, - ); + const twoFactorToken = await generateTwoFactorToken(existingUser.email); + await sendTwoFactorTokenEmail(twoFactorToken.email, twoFactorToken.token); return { twoFactor: true }; } @@ -107,14 +105,14 @@ export const login = async ( email, password, redirectTo: callbackUrl || DEFAULT_LOGIN_REDIRECT, - }) + }); } catch (error) { if (error instanceof AuthError) { switch (error.type) { case "CredentialsSignin": - return { error: "Invalid credentials!" } + return { error: "Invalid credentials!" }; default: - return { error: "Something went wrong!" } + return { error: "Something went wrong!" }; } }