Perfect for: Protecting dashboards, admin panels, subscription features, and role-specific content.
Types of Route Protection
🌍 Public Routes
Accessible by everyone (including unauthenticated users)// No protection needed
export default function PublicPage() {
return <div>Anyone can see this</div>
}🔒 Private Routes
Requires authentication (any logged-in user)// Using withAuth HOC
import { withAuth } from '@/components/features/auth/with-auth'
function DashboardPage() {
return <div>Only logged-in users see this</div>
}
export default withAuth(DashboardPage)👤 Role-Based Routes
Requires specific role or permissionimport { withAuth } from '@/components/features/auth/with-auth'
function ModeratorPanel() {
return <div>Only moderators and above</div>
}
export default withAuth(ModeratorPanel, {
requiredRole: 'MODERATOR'
})👑 Admin Routes
Admin/backoffice access onlyimport { withAuth } from '@/components/features/auth/with-auth'
function AdminDashboard() {
return <div>Admin backoffice</div>
}
export default withAuth(AdminDashboard, {
requiredRole: 'ADMIN',
redirectTo: '/unauthorized'
})Shortcut available: The boilerplate also includes
withAuthAdmin() as a convenient shortcut for admin-only pages. It automatically requires ADMIN role and redirects unauthorized users.withAuth Usage
ThewithAuth HOC has a simple signature based on the actual boilerplate code:
withAuth<P>(WrappedComponent: ComponentType<P & WithAuthProps>, requiredRole?: Roles)// Default protection (USER role)
export default withAuth(MyPage)
// The component receives user props
function MyPage({ user }: WithAuthProps) {
return <div>Hello {user.name}</div>
}Route-Level Middleware
For advanced protection, use Next.js middleware:// src/middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl
// Admin routes protection
if (pathname.startsWith('/admin')) {
const userRole = getUserRoleFromSession(request)
if (!['ADMIN', 'SUPER_ADMIN'].includes(userRole)) {
return NextResponse.redirect(new URL('/unauthorized', request.url))
}
}
// Organization routes protection
if (pathname.startsWith('/organization')) {
const hasOrgAccess = checkOrganizationAccess(request)
if (!hasOrgAccess) {
return NextResponse.redirect(new URL('/dashboard', request.url))
}
}
return NextResponse.next()
}
export const config = {
matcher: ['/admin/:path*', '/organization/:path*']
}Error Pages
Forbidden Page (403)
The boilerplate includes a forbidden page for users who don't have sufficient permissions:// src/app/forbidden.tsx
export default function ForbiddenPage() {
return (
<div className="container mx-auto py-16 text-center">
<h1 className="text-4xl font-bold mb-4">403 - Forbidden</h1>
<p className="text-lg mb-8">You don't have permission to access this resource.</p>
<Link href="/dashboard" className="btn btn-primary">
Go to Dashboard
</Link>
</div>
)
}Practical Examples
Basic Page Protection
// src/app/dashboard/page.tsx
import withAuth, { WithAuthProps } from '@/components/features/auth/with-auth'
import { RoleConst } from '@/services/types/domain/auth-types'
function DashboardPage({ user }: WithAuthProps) {
return (
<div>
<h1>Dashboard</h1>
<p>Welcome {user.name}!</p>
</div>
)
}
// Requires USER role (default)
export default withAuth(DashboardPage)Admin Page Protection
// src/app/admin/page.tsx
import withAuth, { WithAuthProps } from '@/components/features/auth/with-auth'
import { RoleConst } from '@/services/types/domain/auth-types'
function AdminPage({ user }: WithAuthProps) {
return (
<div>
<h1>Admin Panel</h1>
<p>Admin user: {user.name}</p>
</div>
)
}
// Requires ADMIN role
export default withAuth(AdminPage, RoleConst.ADMIN)Using withAuthAdmin Shortcut
// src/app/admin/users/page.tsx
import { withAuthAdmin, WithAuthProps } from '@/components/features/auth/with-auth'
function UserManagementPage({ user }: WithAuthProps) {
return (
<div>
<h1>User Management</h1>
<p>Admin: {user.name}</p>
</div>
)
}
// Shortcut for ADMIN role requirement
export default withAuthAdmin(UserManagementPage)Testing Route Protection
1
Test unauthenticated access
- Try accessing protected routes without login
- Verify correct redirect to login page
- Check unauthorized error messages
2
Test role-based access
- Create users with different roles
- Try accessing protected pages with each role
- Verify correct redirections and permissions
- Test role inheritance works correctly
3
Test middleware protection
- Test route-level middleware rules
- Verify correct redirects for unauthorized access
- Check performance impact of middleware
Pages secured! Your application routes are now protected with flexible, role-based access control that scales with your needs.