The Security Gap
Client-side auth checks (like checking a cookie in JavaScript) are easily bypassed. Real security requires server-side validation.
Our Approach
Every protected page validates the session on the server:
// src/app/(control-center)/admin/page.tsx
export default async function AdminPage() {
const user = await requireRole('ADMIN', 'OWNER');
// Only admins/owners reach this code
const data = await fetchAdminData();
return <AdminDashboard user={user} data={data} />;
}
Proxy-Level Protection
Our proxy.ts adds an additional layer, redirecting unauthenticated requests before they hit page components:
export function proxy(request: NextRequest) {
const session = request.cookies.get('session');
const pathname = request.nextUrl.pathname;
// Protected zones require session
if (isProtectedPath(pathname) && !session) {
return NextResponse.redirect(new URL('/sign-in', request.url));
}
return NextResponse.next();
}
API Route Protection
API routes validate sessions and check roles before processing requests:
export async function GET() {
const { user } = await validateRequest();
if (!user || !['ADMIN', 'OWNER'].includes(user.role)) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
// Process request...
}
Defense in Depth
Multiple layers of protection ensure that even if one layer fails, others catch unauthorized access.



