-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.ts
More file actions
132 lines (120 loc) · 3.95 KB
/
Copy pathauth.ts
File metadata and controls
132 lines (120 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { prisma } from "./lib/prisma";
import CredentialsProvider from "next-auth/providers/credentials";
import { getUserByEmail } from "./lib/data/user";
import bcrypt from "bcryptjs";
// Determine if the code is running in middleware/edge context
const isEdgeRuntime =
typeof process.env.NEXT_RUNTIME === "string" &&
process.env.NEXT_RUNTIME === "edge";
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
CredentialsProvider({
name: "credentials",
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" },
},
async authorize(credentials, request) {
// Ensure credentials have expected shape at runtime
const email =
typeof credentials?.email === "string" ? credentials.email : null;
const password =
typeof credentials?.password === "string"
? credentials.password
: null;
if (!email || !password) return null;
const user = await getUserByEmail(email);
if (!user || !user.password) return null;
const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) return null;
// Normalize fields
return {
...user,
provider: user.provider ?? undefined,
image: user.image ?? null,
} as any;
},
}),
],
// Only use Prisma adapter in non-edge environments and configure it correctly
adapter: isEdgeRuntime ? undefined : PrismaAdapter(prisma),
// Use JWT session strategy which is compatible with Edge
session: {
strategy: "jwt",
},
pages: {
signIn: "/sign-in",
error: "/auth/error", // Add error page
},
debug: process.env.NODE_ENV === "development", // Enable debugging in development
callbacks: {
// Add payment status to the JWT token
jwt: async ({ token, user, account }) => {
if (user) {
if (user.id) token.id = user.id;
if (user.email) token.email = user.email;
// Only add provider if it exists
if (account) {
token.provider = account.provider;
} else {
token.provider = "credentials";
}
// Get payment status from database and add to token
try {
if (user.id) {
// Make sure user.id exists
const userWithPayment = await prisma.user.findUnique({
where: {
id: user.id,
},
select: {
hasPaid: true,
},
});
token.hasPaid = userWithPayment?.hasPaid || false;
}
} catch (error) {
console.error("Error getting payment status:", error);
token.hasPaid = false;
}
}
return token;
},
// Pass payment status to the client session
session: async ({ session, token }) => {
if (session?.user && token) {
session.user.id = token.id as string;
session.user.hasPaid = token.hasPaid as boolean;
if (token.provider) {
session.user.provider = token.provider as string;
}
}
return session;
},
redirect({ url, baseUrl }) {
console.log("Auth redirect called:", { url, baseUrl });
// Simple rule: Always go to dashboard after successful login
if (
url === baseUrl ||
url.includes("/sign-in") ||
url === `${baseUrl}/`
) {
console.log("Redirecting to dashboard");
return `${baseUrl}/dashboard`;
}
// If URL starts with baseUrl, allow it
if (url.startsWith(baseUrl)) {
return url;
}
// Default to baseUrl
return baseUrl;
},
},
});