Broken Function Level Authorization (OWASP API Security Top 10 2023 API5) is what happens when authentication and object-level checks exist but role enforcement doesn't — any logged-in user reaches admin-only functions. CWE-269 (Improper Privilege Management) covers the pattern: the application knows what role a user has but doesn't consult it before executing privileged operations. A user who discovers /api/admin/delete-user or /api/billing/refund-all can invoke it if role checks are missing. Compromised non-admin accounts become full admin accounts. Internal tools are a common gap — developers add auth but skip role checks on 'internal' routes.
High because missing role checks let any authenticated user — including compromised accounts — execute privileged operations like deleting records or modifying system configuration.
Add explicit role assertions at the top of every privileged route handler, not just in middleware. Middleware handles authentication; role authorization belongs at the route level where the required role is clear.
// src/app/api/admin/users/route.ts
export async function DELETE(req: Request) {
const user = await getAuthUser(req)
if (!user) return new Response('Unauthorized', { status: 401 })
// Role check — explicit, not delegated to a generic middleware flag
if (user.role !== 'admin') return new Response('Forbidden', { status: 403 })
const { userId } = await req.json()
await db.user.delete({ where: { id: userId } })
return Response.json({ deleted: true })
}
For complex role hierarchies, centralize checks in a src/lib/authz.ts policy module so role requirements are auditable in one place.
ID: api-security.auth.rbac-enforced
Severity: high
What to look for: Enumerate every relevant item. Check whether endpoints that should only be accessible to certain roles (admin, moderator, premium users) verify the user's role before granting access. Look for role checks in middleware or at the start of route handlers.
Pass criteria: At least 1 of the following conditions is met. Admin-only endpoints check that the authenticated user has an admin role. Other role-restricted endpoints verify the user's role before proceeding. Role checks happen consistently across all restricted endpoints.
Fail criteria: Admin-only endpoints do not check the user's role, or role checks are inconsistent (some endpoints check, others don't).
Skip (N/A) when: The API does not have role-based endpoints or all authenticated users have equal access.
Detail on fail: Name endpoints where role checks are missing. Example: "DELETE /api/users endpoint does not verify admin role — any authenticated user can delete any user" or "PATCH /api/settings allows any authenticated user to modify system settings"
Remediation: Add role checks before executing admin logic:
export default authMiddleware(async (req, res, user) => {
if (user.role !== 'admin') {
return res.status(403).json({ error: 'Admin access required' })
}
// Admin-only logic
await db.user.deleteMany()
res.json({ message: 'All users deleted' })
})