-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathmiddleware.ts
More file actions
98 lines (85 loc) · 3.16 KB
/
middleware.ts
File metadata and controls
98 lines (85 loc) · 3.16 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
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
/**
* Next.js Middleware for route protection
*
* This middleware runs on every request and:
* 1. Protects routes that require authentication (redirects to /login)
* 2. Prevents authenticated users from accessing auth pages (redirects to /)
* 3. Preserves the original URL in a redirect query param for post-login redirect
*
* Protected routes: /account/*, /thank-you, /update-email, /update-password
* Auth routes: /login, /signup
*
* The middleware checks for a "token" cookie set by config/storage.ts
*/
// Define protected routes that require authentication
const protectedRoutes = [
"/account",
"/thank-you",
"/update-email",
"/update-password"
];
// Define auth routes that should redirect to home if already logged in
const authRoutes = ["/login", "/signup"];
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
// Get the token from cookies
const tokenCookie = request.cookies.get("storefront_token")?.value;
// Parse and validate the token
let isAuthenticated = false;
if (tokenCookie) {
try {
const tokenData = JSON.parse(decodeURIComponent(tokenCookie));
// Check if token has access_token
if (tokenData.access_token) {
// If we have created_at and expires_in, check expiration
if (tokenData.created_at && tokenData.expires_in) {
const expiresAt = tokenData.created_at + tokenData.expires_in;
const now = Math.floor(Date.now() / 1000);
isAuthenticated = now < expiresAt;
} else {
// Token exists but missing timestamp info - assume valid
// (this handles legacy tokens or different token formats)
isAuthenticated = true;
}
}
} catch (e) {
// Invalid token format, treat as not authenticated
isAuthenticated = false;
console.error("[Middleware] Token parse error:", e);
}
}
// Check if the current path is a protected route
const isProtectedRoute = protectedRoutes.some((route) =>
pathname.startsWith(route)
);
// Check if the current path is an auth route
const isAuthRoute = authRoutes.some((route) => pathname.startsWith(route));
// If user is not authenticated and trying to access protected route
if (isProtectedRoute && !isAuthenticated) {
const loginUrl = new URL("/login", request.url);
// Add the original URL as a redirect parameter
loginUrl.searchParams.set("redirect", pathname);
return NextResponse.redirect(loginUrl);
}
// If user is authenticated and trying to access auth routes, redirect to home
if (isAuthRoute && isAuthenticated) {
return NextResponse.redirect(new URL("/", request.url));
}
return NextResponse.next();
}
// Configure which routes should run the middleware
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* - public folder
*/
"/((?!api|_next/static|_next/image|favicon.ico|.*\\..*|public).*)"
]
};