-
Notifications
You must be signed in to change notification settings - Fork 107
/
Copy pathmiddleware.ts
123 lines (105 loc) · 3.09 KB
/
middleware.ts
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
import type { NextFunction, Request, Response } from "express";
import jwt from "jsonwebtoken";
import { clerkClient } from "@clerk/clerk-sdk-node";
declare global {
namespace Express {
interface Request {
userId?: string;
user?: {
role?: "admin" | "user";
email: string;
};
}
}
}
export async function authMiddleware(
req: Request,
res: Response,
next: NextFunction
) {
try {
console.log("Authenticating request");
const authHeader = req.headers["authorization"];
const token = authHeader?.split(" ")[1];
if (!token) {
res.status(401).json({ message: "No token provided" });
return;
}
// Debug logs
console.log("Received token:", token);
// Get the JWT verification key from environment variable
const publicKey = process.env.CLERK_JWT_PUBLIC_KEY!;
if (!publicKey) {
console.error("Missing CLERK_JWT_PUBLIC_KEY in environment variables");
res.status(500).json({ message: "Server configuration error" });
return;
}
// Format the public key properly
const formattedKey = publicKey.replace(/\\n/g, "\n");
const decoded = jwt.verify(token, formattedKey, {
algorithms: ["RS256"],
issuer:
process.env.CLERK_ISSUER || "https://clerk.100xdevs.com",
complete: true,
});
console.log("Decoded token:", decoded);
// Extract user ID from the decoded token
const userId = (decoded as any).payload.sub;
if (!userId) {
console.error("No user ID in token payload");
res.status(403).json({ message: "Invalid token payload" });
return;
}
// Fetch user details from Clerk
const user = await clerkClient.users.getUser(userId);
console.log("User details:", user);
const primaryEmail = user.emailAddresses.find(
(email) => email.id === user.primaryEmailAddressId
);
if (!primaryEmail) {
console.error("No email found for user");
res.status(400).json({ message: "User email not found" });
return;
}
// Attach the user ID and email to the request
req.userId = userId;
req.user = {
role: (user.publicMetadata.role as "admin" | "user") || "user",
email: primaryEmail.emailAddress,
};
next();
} catch (error) {
console.error("Auth error:", error);
if (error instanceof jwt.JsonWebTokenError) {
res.status(403).json({
message: "Invalid token",
details:
process.env.NODE_ENV === "development" ? error.message : undefined,
});
return;
}
res.status(500).json({
message: "Error processing authentication",
details:
process.env.NODE_ENV === "development"
? (error as Error).message
: undefined,
});
return;
}
}
export async function adminMiddleware(
req: Request,
res: Response,
next: NextFunction
) {
console.log("Checking user role");
await authMiddleware(req, res, () => {
console.log("User role:", req.user?.role);
if (req.user?.role !== "admin") {
res.status(403).json({ error: "Unauthorized" });
return;
}
next();
});
}