Auth Route Protection Checker
To audit and enhance authentication protection across Next.js routes, server components, and API routes, follow these steps systematically.
Step 1: Discover Project Structure
Identify all files that need authentication checks:
- •
Use Glob to find all route files:
- •
app/**/page.tsx- Page components - •
app/**/route.ts- API routes - •
app/**/layout.tsx- Layout components - •
lib/actions/**/*.ts- Server actions
- •
- •
Read middleware configuration:
- •
middleware.ts- Current middleware setup - •
next.config.js- Route configuration
- •
- •
Identify authentication setup:
- •Search for auth client files (Supabase, NextAuth, Clerk, etc.)
- •Find auth utility functions
Step 2: Analyze Current Protection
For each discovered file, check for existing auth protection:
Check for Authentication Patterns
Use Grep to search for:
- "auth.getUser()" - "getSession()" - "currentUser()" - "requireAuth" - "redirect.*login" - "unauthorized" - "createServerClient"
Identify Protection Gaps
Flag files that:
- •Have no auth checks
- •Are in protected routes but lack verification
- •Accept user input without auth validation
- •Perform privileged operations without role checks
Consult references/protection-patterns.md for common patterns.
Step 3: Categorize Routes by Protection Level
Classify routes into security categories:
Public Routes - No auth required:
- •Landing pages
- •Marketing content
- •Public blog posts
- •Login/signup pages
Authenticated Routes - Login required:
- •User dashboard
- •Profile pages
- •User-specific data
Role-Protected Routes - Specific roles required:
- •Admin panels
- •Moderator tools
- •Premium features
Action-Protected Routes - Specific permissions required:
- •Edit operations
- •Delete operations
- •Admin actions
Step 4: Generate Protection Report
Create a comprehensive audit report:
# Route Protection Audit Report Generated: [timestamp] ## Summary - Total Routes: X - Protected: Y - Unprotected: Z - Needs Review: N ## Unprotected Routes ### Critical (Requires immediate attention) - [ ] /app/admin/page.tsx - Admin panel with no auth check - [ ] /app/api/users/delete/route.ts - Delete endpoint unprotected ### High Priority - [ ] /app/dashboard/page.tsx - User dashboard missing auth - [ ] /app/api/data/route.ts - API route needs auth ### Medium Priority - [ ] /app/profile/page.tsx - Profile page needs verification ### Low Priority (Review recommended) - [ ] /app/about/page.tsx - Consider if auth needed ## Protected Routes ### Properly Protected - [x] /app/(protected)/settings/page.tsx - Has auth check - [x] /app/api/auth/logout/route.ts - Auth verified ### Needs Enhancement - [~] /app/admin/users/page.tsx - Has auth but no role check - [~] /app/api/posts/route.ts - Auth exists but no rate limiting
Step 5: Generate Protection Code
For each unprotected route, generate appropriate protection code:
Server Component Protection
// app/protected-page/page.tsx
import { createServerClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'
export default async function ProtectedPage() {
const supabase = createServerClient()
const { data: { user }, error } = await supabase.auth.getUser()
if (error || !user) {
redirect('/login')
}
// Optional: Role check
const { data: profile } = await supabase
.from('profiles')
.select('role')
.eq('id', user.id)
.single()
if (profile?.role !== 'admin') {
redirect('/unauthorized')
}
return <div>Protected Content</div>
}
API Route Protection
// app/api/protected/route.ts
import { createServerClient } from '@/lib/supabase/server'
import { NextResponse } from 'next/server'
export async function GET(request: Request) {
const supabase = createServerClient()
const { data: { user }, error } = await supabase.auth.getUser()
if (error || !user) {
return NextResponse.json(
{ error: 'Unauthorized' },
{ status: 401 }
)
}
// Optional: Role-based access
const userRole = user.user_metadata?.role
if (userRole !== 'admin') {
return NextResponse.json(
{ error: 'Forbidden - Admin access required' },
{ status: 403 }
)
}
// Protected logic here
return NextResponse.json({ data: 'protected data' })
}
Server Action Protection
// lib/actions/admin.ts
'use server'
import { createServerClient } from '@/lib/supabase/server'
import { revalidatePath } from 'next/cache'
export async function deleteUser(userId: string) {
const supabase = createServerClient()
// Auth check
const { data: { user }, error } = await supabase.auth.getUser()
if (error || !user) {
throw new Error('Unauthorized')
}
// Role check
const { data: profile } = await supabase
.from('profiles')
.select('role')
.eq('id', user.id)
.single()
if (profile?.role !== 'admin') {
throw new Error('Forbidden - Admin access required')
}
// Permission check (optional)
const canDeleteUsers = await checkPermission(user.id, 'users:delete')
if (!canDeleteUsers) {
throw new Error('Insufficient permissions')
}
// Perform action
const { error: deleteError } = await supabase
.from('users')
.delete()
.eq('id', userId)
if (deleteError) throw deleteError
revalidatePath('/admin/users')
}
Middleware Protection
// middleware.ts
import { createServerClient } from '@/lib/supabase/middleware'
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export async function middleware(request: NextRequest) {
const response = NextResponse.next()
const supabase = createServerClient(request, response)
const { data: { user } } = await supabase.auth.getUser()
// Protected routes
const protectedRoutes = ['/dashboard', '/profile', '/settings']
const isProtectedRoute = protectedRoutes.some(route =>
request.nextUrl.pathname.startsWith(route)
)
if (isProtectedRoute && !user) {
return NextResponse.redirect(new URL('/login', request.url))
}
// Admin routes
const adminRoutes = ['/admin']
const isAdminRoute = adminRoutes.some(route =>
request.nextUrl.pathname.startsWith(route)
)
if (isAdminRoute) {
if (!user) {
return NextResponse.redirect(new URL('/login', request.url))
}
const { data: profile } = await supabase
.from('profiles')
.select('role')
.eq('id', user.id)
.single()
if (profile?.role !== 'admin') {
return NextResponse.redirect(new URL('/unauthorized', request.url))
}
}
return response
}
export const config = {
matcher: [
'/dashboard/:path*',
'/profile/:path*',
'/settings/:path*',
'/admin/:path*',
]
}
Step 6: Generate Helper Functions
Create reusable auth utilities using templates from assets/auth-helpers.ts:
// lib/auth/helpers.ts
import { createServerClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'
export async function requireAuth() {
const supabase = createServerClient()
const { data: { user }, error } = await supabase.auth.getUser()
if (error || !user) {
redirect('/login')
}
return user
}
export async function requireRole(allowedRoles: string[]) {
const user = await requireAuth()
const supabase = createServerClient()
const { data: profile } = await supabase
.from('profiles')
.select('role')
.eq('id', user.id)
.single()
if (!profile || !allowedRoles.includes(profile.role)) {
redirect('/unauthorized')
}
return { user, role: profile.role }
}
export async function checkPermission(
userId: string,
permission: string
): Promise<boolean> {
const supabase = createServerClient()
const { data } = await supabase
.from('user_permissions')
.select('permission')
.eq('user_id', userId)
.eq('permission', permission)
.single()
return !!data
}
Step 7: Create Testing Suite
Generate tests to verify protection works:
Use templates from assets/auth-tests.ts:
// tests/auth-protection.test.ts
import { describe, it, expect } from 'vitest'
import { GET } from '@/app/api/protected/route'
describe('Route Protection', () => {
it('returns 401 for unauthenticated requests', async () => {
const request = new Request('http://localhost/api/protected')
const response = await GET(request)
expect(response.status).toBe(401)
})
it('returns 403 for unauthorized role', async () => {
// Mock auth with non-admin user
const response = await GET(mockRequestWithUser({ role: 'user' }))
expect(response.status).toBe(403)
})
it('allows access for admin users', async () => {
const response = await GET(mockRequestWithUser({ role: 'admin' }))
expect(response.status).toBe(200)
})
})
Step 8: Generate Documentation
Create documentation for the protection system:
# Authentication & Authorization Guide ## Overview This application uses [Auth Provider] for authentication and role-based access control. ## Route Protection Levels ### Public Routes - No authentication required - Accessible to all visitors - Examples: /, /about, /login ### Authenticated Routes - Requires user login - No specific role needed - Examples: /dashboard, /profile ### Role-Protected Routes - Requires specific role(s) - Examples: /admin (admin role) ### Permission-Protected Routes - Requires specific permissions - Granular access control - Examples: /admin/delete-user (users:delete permission) ## Implementation Patterns [Include code examples and usage guidelines]
Step 9: Suggest Improvements
Based on the audit, suggest security enhancements:
- •Middleware Coverage: Routes missing from middleware config
- •Consistent Patterns: Inconsistent auth check implementations
- •Error Handling: Better error messages and redirects
- •Rate Limiting: API routes needing rate limits
- •CSRF Protection: Forms needing CSRF tokens
- •Audit Logging: Privileged actions needing logging
Consult references/security-best-practices.md for recommendations.
Implementation Guidelines
Best Practices
- •Always check auth on server side, never trust client
- •Use middleware for route-based protection
- •Add role/permission checks for sensitive operations
- •Implement proper error handling and redirects
- •Log authentication failures and suspicious activity
- •Use HTTPS in production
- •Implement rate limiting on auth endpoints
Common Patterns
Consult references/protection-patterns.md for:
- •Server component auth checks
- •API route protection
- •Server action security
- •Middleware configuration
- •Role-based access control
- •Permission-based access control
Output Format
Generate files:
reports/ auth-audit-[timestamp].md security/ auth-helpers.ts (if missing) middleware.ts (enhanced version) tests/ auth-protection.test.ts docs/ auth-guide.md
Verification Checklist
Before completing:
- • All routes categorized by protection level
- • Critical unprotected routes identified
- • Protection code generated for gaps
- • Helper functions created/updated
- • Middleware configured correctly
- • Tests cover auth scenarios
- • Documentation updated
Consulting References
Throughout analysis:
- •Consult
references/protection-patterns.mdfor auth patterns - •Consult
references/security-best-practices.mdfor guidelines - •Use templates from
assets/auth-helpers.ts - •Use test templates from
assets/auth-tests.ts
Completion
When finished:
- •Display audit report summary
- •Highlight critical issues
- •Provide generated protection code
- •List implementation steps
- •Offer to apply fixes or provide guidance