diff --git a/src/app/email_templates/magic_link.ts b/src/app/email_templates/magic_link.ts index 82c44a8..de84b41 100644 --- a/src/app/email_templates/magic_link.ts +++ b/src/app/email_templates/magic_link.ts @@ -27,7 +27,7 @@ export async function MagicLinksEmail({ } // Create a clean login link instead of the NextAuth callback - const loginUrl = `${parsed.origin}/login/${token}/${encodeURIComponent(email)}`; + const loginUrl = `${parsed.origin}/verify/${token}`; const transport = createTransport(provider.server); diff --git a/src/app/login/[token]/[email]/page.tsx b/src/app/login/[token]/[email]/page.tsx deleted file mode 100644 index 94fef5d..0000000 --- a/src/app/login/[token]/[email]/page.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { redirect } from "next/navigation"; - -export default async function LoginPage({ - params, -}: { - params: Promise<{ token: string; email: string }>; -}) { - const { token, email } = await params; - - if (!token || !email) { - redirect("/"); - } - - const decodedEmail = decodeURIComponent(email); - - redirect( - `/api/auth/callback/email?token=${token}&email=${encodeURIComponent(decodedEmail)}`, - ); -} diff --git a/src/app/verify/[token]/page.tsx b/src/app/verify/[token]/page.tsx new file mode 100644 index 0000000..7ba7251 --- /dev/null +++ b/src/app/verify/[token]/page.tsx @@ -0,0 +1,44 @@ +import { redirect } from "next/navigation"; +import { db } from "@/app/db/db"; +import { verificationTokens } from "@/app/db/schema/users"; +import { eq } from "drizzle-orm"; +import crypto from "crypto"; + +async function getEmailByToken(token: string) { + const secret = process.env.NEXTAUTH_SECRET!; + + const hashedToken = crypto + .createHash("sha256") + .update(token + secret) + .digest("hex"); + + const record = await db + .select() + .from(verificationTokens) + .where(eq(verificationTokens.token, hashedToken)) + .limit(1); + + if (!record.length) { + return null; + } + + return record[0].identifier; +} + +export default async function LoginPage({ + params, +}: { + params: Promise<{ token: string }>; +}) { + const { token } = await params; + + const email = await getEmailByToken(token); + + if (!email) { + redirect("/"); + } + + redirect( + `/api/auth/callback/email?token=${token}&email=${encodeURIComponent(email)}`, + ); +}