IDOR in Next.js Applications
IDOR occurs in Next.js when API routes and Server Actions accept resource IDs from requests without verifying that the authenticated user has permission to access them. Simply checking if a user is logged in is not enough - you must verify they own or have access to the specific resource.
Scan Your Next.js AppHow IDOR Manifests in Next.js
IDOR in Next.js appears as: API routes like /api/users/[id] that return any user's data if you change the ID parameter, without checking if the requester owns that data. Server Actions that accept a record ID and perform operations without verifying ownership. Dynamic routes like /dashboard/invoices/[id] where the server component fetches data by ID without an authorization check. File download endpoints where changing a file ID gives access to other users' files.
Real-World Impact
A Next.js invoicing app allowed users to view invoices at /api/invoices/[id]. By incrementing the numeric ID, an attacker enumerated all invoices in the system, accessing financial data, client names, and billing addresses belonging to other businesses.
Step-by-Step Fix
Scope queries to the authenticated user
Always include the user ID in database queries to ensure ownership.
// UNSAFE - fetches any user's invoice
export async function GET(req: Request, { params }: { params: { id: string } }) {
const invoice = await db.invoice.findUnique({ where: { id: params.id } });
return Response.json(invoice);
}
// SAFE - scoped to authenticated user
export async function GET(req: Request, { params }: { params: { id: string } }) {
const session = await getServerSession(authOptions);
if (!session) return Response.json({ error: 'Unauthorized' }, { status: 401 });
const invoice = await db.invoice.findFirst({
where: {
id: params.id,
userId: session.user.id, // Ownership check
},
});
if (!invoice) return Response.json({ error: 'Not found' }, { status: 404 });
return Response.json(invoice);
}Create an authorization helper
Build a reusable function for checking resource access.
// lib/authorize.ts
export async function authorizeResource(
resourceId: string,
userId: string,
table: 'invoice' | 'project' | 'document'
) {
const resource = await db[table].findFirst({
where: { id: resourceId, userId },
});
if (!resource) throw new Error('Forbidden');
return resource;
}
// Usage in API route
const invoice = await authorizeResource(params.id, session.user.id, 'invoice');Use UUIDs instead of sequential IDs
Prevent ID enumeration by using unpredictable identifiers.
// In your Prisma schema
model Invoice {
id String @id @default(cuid())
userId String
amount Int
createdAt DateTime @default(now())
}
// Or use UUID
model Invoice {
id String @id @default(uuid())
// ...
}Prevention Best Practices
1. Always check resource ownership in addition to authentication. 2. Use the session's user ID to scope all database queries. 3. Use UUIDs instead of sequential IDs to prevent enumeration. 4. Create authorization middleware or helper functions. 5. Never trust IDs from URL parameters or request bodies without verification.
How to Test
1. Log in as User A, access a resource, note the ID. 2. Log in as User B, try accessing User A's resource ID. 3. Test API routes by changing IDs in requests. 4. Check if sequential IDs allow enumeration. 5. Use Vibe App Scanner to detect IDOR patterns in your Next.js application.
Frequently Asked Questions
What is the difference between broken auth and IDOR?
Broken auth means a user can access endpoints without being logged in. IDOR means a logged-in user can access resources belonging to other users by manipulating IDs. Both are access control failures but at different levels.
Do UUIDs prevent IDOR?
UUIDs make IDOR harder to exploit because IDs cannot be guessed or enumerated. However, they do not prevent IDOR entirely - if a UUID is leaked (in URLs, logs, etc.), the resource is still accessible. Always combine UUIDs with ownership checks.
How do I test for IDOR in Next.js?
Create two test accounts. Access resources with Account A, then try the same URLs with Account B. If Account B can see Account A's data, you have an IDOR vulnerability. Automate this by scripting API calls with different session tokens.
Related Security Resources
Is Your Next.js App Vulnerable to IDOR?
VAS automatically scans for idor vulnerabilities in Next.js applications and provides step-by-step remediation guidance with code examples.
Scans from $5, results in minutes. Get actionable fixes tailored to your Next.js stack.