-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmiddleware.ts
More file actions
81 lines (72 loc) · 2.28 KB
/
Copy pathmiddleware.ts
File metadata and controls
81 lines (72 loc) · 2.28 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
/**
* Next.js Middleware for Supabase Authentication
*
* This middleware runs on every request to:
* 1. Refresh the auth session (keeps user logged in)
* 2. Protect routes that require authentication
* 3. Redirect unauthenticated users to login
*
* SECURITY NOTES:
* - Runs on EVERY matched request (zero trust)
* - Session is validated with Supabase on each request
* - API routes return 401, page routes redirect to login
* - Double-check auth in API routes for defense in depth
*/
import { NextResponse, type NextRequest } from "next/server";
import {
updateSession,
isProtectedRoute,
isAuthRoute,
getLoginUrl,
createUnauthorizedResponse,
} from "@/lib/supabase/middleware";
export async function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Skip middleware for static files and Next.js internals
if (
pathname.startsWith("/_next") ||
pathname.startsWith("/favicon") ||
pathname.includes(".")
) {
return NextResponse.next();
}
// Update session (refresh token if needed)
const { response, user } = await updateSession(request);
// Check if route requires authentication
if (isProtectedRoute(pathname)) {
if (!user) {
// API routes: return 401 JSON response
if (pathname.startsWith("/api/")) {
return createUnauthorizedResponse();
}
// Page routes: redirect to login
return NextResponse.redirect(getLoginUrl(request));
}
}
// If user is logged in and tries to access auth pages, redirect to dashboard
if (isAuthRoute(pathname) && user) {
// Don't redirect from callback or confirm routes
if (!pathname.includes("/callback") && !pathname.includes("/confirm")) {
return NextResponse.redirect(new URL("/dashboard", request.url));
}
}
return response;
}
/**
* Middleware matcher configuration
*
* This defines which routes the middleware runs on.
* Excludes static files and public assets for performance.
*/
export const config = {
matcher: [
/*
* Match all request paths except:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* - public folder files (images, etc.)
*/
"/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
],
};