Skip to content

Commit bf1d827

Browse files
Merge pull request #21 from Abdulgafar4/feature/auth-middleware
feat: enhance middleware with authentication and locale handling
2 parents aac8716 + a2d75f3 commit bf1d827

1 file changed

Lines changed: 94 additions & 5 deletions

File tree

frontend/src/middleware.ts

Lines changed: 94 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,103 @@ function getLocale(request: NextRequest): string | undefined {
4747
}
4848
}
4949

50+
/**
51+
* Check if user is authenticated by verifying auth token in cookies
52+
*/
53+
function isAuthenticated(request: NextRequest): boolean {
54+
const authToken = request.cookies.get('auth_token');
55+
const sessionToken = request.cookies.get('session_token');
56+
57+
// Check for either auth_token or session_token
58+
// You can customize this based on your authentication mechanism
59+
return !!(authToken || sessionToken);
60+
}
61+
62+
/**
63+
* Extract locale from pathname
64+
*/
65+
function extractLocale(pathname: string): string | null {
66+
const localeRegex = new RegExp(`^/(${i18n.locales.join('|')})`);
67+
const match = pathname.match(localeRegex);
68+
return match ? match[1] : null;
69+
}
70+
71+
/**
72+
* Get pathname without locale prefix
73+
*/
74+
function getPathnameWithoutLocale(pathname: string): string {
75+
const locale = extractLocale(pathname);
76+
if (locale) {
77+
return pathname.replace(`/${locale}`, '') || '/';
78+
}
79+
return pathname;
80+
}
81+
82+
/**
83+
* Check if path is a public route (doesn't require authentication)
84+
*/
85+
function isPublicRoute(pathname: string): boolean {
86+
const pathWithoutLocale = getPathnameWithoutLocale(pathname);
87+
88+
// Public routes that don't require authentication
89+
const publicRoutes = [
90+
'/login',
91+
'/signup',
92+
'/register',
93+
'/forgot-password',
94+
'/reset-password',
95+
];
96+
97+
// Check if path starts with any public route
98+
return publicRoutes.some(route => pathWithoutLocale.startsWith(route));
99+
}
100+
101+
/**
102+
* Check if path is a protected route (requires authentication)
103+
* By default, all routes are protected except explicitly public ones
104+
*/
105+
function isProtectedRoute(pathname: string): boolean {
106+
const pathWithoutLocale = getPathnameWithoutLocale(pathname);
107+
108+
// If it's a public route, it's not protected
109+
if (isPublicRoute(pathname)) {
110+
return false;
111+
}
112+
113+
// All other routes (dashboard routes, home, etc.) are protected by default
114+
// This includes: /, /my_books, /books, /profile, /settings, etc.
115+
return true;
116+
}
117+
50118
export function middleware(request: NextRequest) {
51119
const pathname = request.nextUrl.pathname;
120+
const authenticated = isAuthenticated(request);
121+
const locale = extractLocale(pathname) || getLocale(request) || i18n.defaultLocale;
122+
const pathWithoutLocale = getPathnameWithoutLocale(pathname);
123+
const isPublic = isPublicRoute(pathname);
124+
const isProtected = isProtectedRoute(pathname);
52125

53-
// Check if the path is missing the locale
126+
// Handle locale routing first
54127
const pathnameIsMissingLocale = i18n.locales.every(
55128
(locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
56129
);
57130

58-
if (pathnameIsMissingLocale) {
59-
// Get the locale (from cookie or fallback to browser preferences)
60-
const locale = getLocale(request) || i18n.defaultLocale;
131+
// Authentication checks (after locale extraction, before locale routing)
132+
// If accessing a protected route without authentication, redirect to login
133+
if (isProtected && !authenticated) {
134+
const loginUrl = new URL(`/${locale}/login`, request.url);
135+
loginUrl.searchParams.set('redirect', pathname);
136+
return NextResponse.redirect(loginUrl);
137+
}
138+
139+
// If authenticated user tries to access auth pages (login, signup), redirect to home
140+
if (authenticated && isPublic) {
141+
const homeUrl = new URL(`/${locale}`, request.url);
142+
return NextResponse.redirect(homeUrl);
143+
}
61144

145+
// Handle locale prefixing
146+
if (pathnameIsMissingLocale) {
62147
// For default locale, rewrite internally (don't redirect)
63148
if (locale === i18n.defaultLocale) {
64149
const newUrl = request.nextUrl.clone();
@@ -77,9 +162,13 @@ export function middleware(request: NextRequest) {
77162
return response;
78163
}
79164

80-
// If path has a locale, just continue
165+
// If path has a locale, continue
81166
const response = NextResponse.next();
82167
response.headers.set('x-pathname', pathname);
168+
169+
// Add authentication status to headers for server components
170+
response.headers.set('x-authenticated', authenticated ? 'true' : 'false');
171+
83172
return response;
84173
}
85174

0 commit comments

Comments
 (0)