diff --git a/.env.example b/.env.example
index 9cb7fa8..882a929 100644
--- a/.env.example
+++ b/.env.example
@@ -16,9 +16,5 @@ NEXTAUTH_URL="http://localhost:3000"
# MongoDB Details
DATABASE_URL=
-# Next Auth Discord Provider
-DISCORD_CLIENT_ID=""
-DISCORD_CLIENT_SECRET=""
-
# Admin account details
ADMIN_PASSWORD="password"
\ No newline at end of file
diff --git a/src/env.mjs b/src/env.mjs
index 63b4be4..174ec54 100644
--- a/src/env.mjs
+++ b/src/env.mjs
@@ -18,9 +18,6 @@ const server = z.object({
// VERCEL_URL doesn't include `https` so it cant be validated as a URL
process.env.VERCEL ? z.string().min(1) : z.string().url()
),
- // Add `.min(1) on ID and SECRET if you want to make sure they're not empty
- DISCORD_CLIENT_ID: z.string(),
- DISCORD_CLIENT_SECRET: z.string(),
});
/**
diff --git a/src/server/auth.ts b/src/server/auth.ts
index 7e6d826..0d140f1 100644
--- a/src/server/auth.ts
+++ b/src/server/auth.ts
@@ -4,10 +4,17 @@ import {
type NextAuthOptions,
type DefaultSession,
} from "next-auth";
-import DiscordProvider from "next-auth/providers/discord";
+import CredentialsProvider from "next-auth/providers/credentials";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
-import { env } from "~/env.mjs";
import { prisma } from "~/server/db";
+import { loginSchema } from "~/lib/validation/auth";
+import { verify } from "argon2";
+
+interface SessionUser {
+ id: string;
+ name: string;
+ username: string;
+}
/**
* Module augmentation for `next-auth` types. Allows us to add custom properties to the `session`
@@ -19,6 +26,7 @@ declare module "next-auth" {
interface Session extends DefaultSession {
user: {
id: string;
+ username: string;
// ...other properties
// role: UserRole;
} & DefaultSession["user"];
@@ -47,9 +55,39 @@ export const authOptions: NextAuthOptions = {
},
adapter: PrismaAdapter(prisma),
providers: [
- DiscordProvider({
- clientId: env.DISCORD_CLIENT_ID,
- clientSecret: env.DISCORD_CLIENT_SECRET,
+ CredentialsProvider({
+ // The name to display on the sign in form (e.g. 'Sign in with...')
+ name: "Credentials",
+ // The credentials is used to generate a suitable form on the sign in page.
+ // You can specify whatever fields you are expecting to be submitted.
+ // e.g. domain, username, password, 2FA token, etc.
+ // You can pass any HTML attribute to the tag through the object.
+ credentials: {
+ username: { label: "Username", type: "text" },
+ password: { label: "Password", type: "password" },
+ },
+ async authorize(credentials): Promise {
+ // get the username and password from the credientials
+ const { username, password } = await loginSchema.parseAsync(
+ credentials
+ );
+
+ // check if username exists in the database
+ const result = await prisma.user.findFirst({
+ where: { username },
+ });
+ if (!result) return null;
+
+ // check if input password match the hashed password
+ const isValidPassword = await verify(result.password, password);
+ if (!isValidPassword) return null;
+
+ return {
+ id: result.id,
+ name: result.name,
+ username,
+ };
+ },
}),
/**
* ...add more providers here.