use signIn callback instead middleware

This commit is contained in:
notmd
2023-01-29 22:59:45 +07:00
parent a7ff5e5f21
commit f75d02c33a
3 changed files with 30 additions and 45 deletions
+1 -36
View File
@@ -1,7 +1,5 @@
import { NextResponse } from "next/server";
import { NextRequestWithAuth, withAuth } from "next-auth/middleware";
export { default } from "next-auth/middleware";
import { checkCaptcha } from "./lib/captcha";
/**
* Guards these pages and redirects them to the sign in page.
*/
@@ -16,38 +14,5 @@ export const config = {
"/tasks/:path*",
"/leaderboard",
"/messages/:path*",
"/api/auth/signin/email",
],
};
const middleware = async (req: NextRequestWithAuth) => {
if (req.method === "POST" && req.nextUrl.pathname === "/api/auth/signin/email") {
const data = await getBody(req);
const res = await checkCaptcha(data?.captcha, req.ip);
if (res.success) {
return NextResponse.next();
}
const url = req.nextUrl.clone();
url.pathname = "/api/auth/invalid-captcha";
return NextResponse.redirect(url);
}
return withAuth(req);
};
async function getBody(req: Request): Promise<Record<string, any> | undefined> {
if (!("body" in req) || !req.body || req.method !== "POST") return;
const contentType = req.headers.get("content-type");
if (contentType?.includes("application/json")) {
return await req.json();
} else if (contentType?.includes("application/x-www-form-urlencoded")) {
const params = new URLSearchParams(await req.text());
return Object.fromEntries(params);
}
}
export default middleware;
+29 -2
View File
@@ -1,11 +1,13 @@
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { boolean } from "boolean";
import { NextApiRequest, NextApiResponse } from "next";
import type { AuthOptions } from "next-auth";
import NextAuth from "next-auth";
import { Provider } from "next-auth/providers";
import CredentialsProvider from "next-auth/providers/credentials";
import DiscordProvider from "next-auth/providers/discord";
import EmailProvider from "next-auth/providers/email";
import { checkCaptcha } from "src/lib/captcha";
import prisma from "src/lib/prismadb";
import { generateUsername } from "unique-username-generator";
@@ -74,7 +76,7 @@ const adminUserMap = process.env.ADMIN_USERS.split(",").reduce((result, entry) =
return result;
}, new Map());
export const authOptions: AuthOptions = {
const authOptions: AuthOptions = {
// Ensure we can store user data in a database.
adapter: PrismaAdapter(prisma),
providers,
@@ -153,4 +155,29 @@ export const authOptions: AuthOptions = {
},
};
export default NextAuth(authOptions);
export default function auth(req: NextApiRequest, res: NextApiResponse) {
return NextAuth(req, res, {
...authOptions,
callbacks: {
...authOptions.callbacks,
async signIn({ account }) {
if (account.provider !== "email") {
return true;
}
const captcha = req.body.captcha;
// https://stackoverflow.com/questions/66111742/get-the-client-ip-on-nextjs-and-use-ssr
const forwarded = req.headers["x-forwarded-for"];
const ip = typeof forwarded === "string" ? forwarded.split(/, /)[0] : req.socket.remoteAddress;
const res = await checkCaptcha(captcha, ip);
if (res.success) {
return true;
}
return "/auth/signin?error=InvalidCaptcha";
},
},
});
}
@@ -1,7 +0,0 @@
import { NextApiRequest, NextApiResponse } from "next";
export default function handler(_: NextApiRequest, res: NextApiResponse) {
return res.status(200).json({
url: "/auth/signin?error=InvalidCaptcha",
});
}