What is Broken Function Level Authorization?
Your app has an admin panel at /api/admin/users that lists every user in the system. The route checks if (session) — meaning anyone who's logged in can access it. A regular member hits that endpoint and gets back the full user list, including emails, roles, and metadata.
This is different from IDOR, where the issue is accessing another user's specific resource. Broken function level auth is about accessing entire features you shouldn't have — admin dashboards, moderation tools, billing management, user deletion endpoints. The function itself is off-limits for your role, but the server never checks.
It's one of the most common bugs in AI-built apps because role-based access control requires understanding your app's permission model. AI generators don't know that /api/admin/* routes should be restricted to admins. They just make sure the route works.
How does Broken Function Level Authorization work?
The vulnerability comes down to a single missing condition. The server checks authentication ("is someone logged in?") but skips authorization ("are they allowed to do this?").
Here's what this looks like in a typical Next.js API route:
// app/api/admin/users/route.ts
export async function GET(req: Request) {
const session = await getSession(req);
if (!session) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
// Problem: any logged-in user can access this.
// A member gets the same data as an admin.
const users = await db.user.findMany();
return Response.json(users);
}// lib/auth-middleware.ts
export function requireRole(allowedRoles: string[]) {
return async (req: Request) => {
const session = await getSession(req);
if (!session) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
if (!allowedRoles.includes(session.user.role)) {
return Response.json({ error: "Forbidden" }, { status: 403 });
}
return session;
};
}
// app/api/admin/users/route.ts
export async function GET(req: Request) {
const session = await requireRole(['admin'])(req);
if (session instanceof Response) return session;
const users = await db.user.findMany();
return Response.json(users);
}Why do AI tools generate Broken Function Level Authorization vulnerabilities?
AI code generators treat authentication and authorization as the same thing. They're not. Authentication is "who are you?" — authorization is "what are you allowed to do?" AI consistently handles the first and forgets the second.
- Prompts say "add auth" — not "add role-based access control." When you ask for authentication, the AI adds session checks. It doesn't infer that certain routes need role gates too.
- Role hierarchies are app-specific. The AI doesn't know your app has admins, managers, and members — or which routes belong to which role. That context isn't in the prompt.
- The admin panel "works" in development. You're testing as an admin during dev. Every route returns data. The AI-generated code passes your manual checks because you have the right role.
The gap between "logged in" and "authorized" is where this bug lives. AI tools close the first gap reliably. The second one requires explicit role modeling that builders need to define themselves.
Common Broken Function Level Authorization patterns
Admin routes with session-only checks
/api/admin/* endpoints that check if (session) instead of if (session.user.role === "admin"). Any logged-in user gets admin access.
Hidden UI but exposed endpoints
The admin link is hidden from non-admin users in the frontend, but the API endpoint behind it has no role check. Security by obscurity.
Role check on GET but not on POST/DELETE
The list endpoint checks roles, but the create or delete endpoints only check authentication. A regular user can't list admins but can delete them.
Middleware applied inconsistently
A role-checking middleware exists but is only applied to some routes. New routes added later skip it because the developer forgot.
How Flowpatrol detects Broken Function Level Authorization
Flowpatrol tests your authorization model the way a curious user would — by logging in with different roles and trying to access things that should be off-limits:
- 1Creates users with different roles — registers or logs in as both a regular user and a privileged user.
- 2Maps the admin surface — discovers admin-only endpoints by crawling the app with a privileged session.
- 3Replays admin requests as a regular user — takes every admin endpoint and calls it with the regular user's session token.
- 4Flags unauthorized access — reports any endpoint where a lower-privilege user gets a 200 instead of a 403.
If a member can hit an admin endpoint and get data back, Flowpatrol catches it. No guesswork — real requests, real responses, real proof.
Related terms
Check your app for missing role checks.
Flowpatrol logs in as different user roles and tests every endpoint. Find out if your admin routes are actually locked down.
Try it free