REST & GraphQL API Security: Preventing BOLA, Mass Assignment, and Token Hijacking
A practical guide to securing modern web services against the OWASP API Security Top 10 vulnerabilities.
1. Why API Security Differs from Traditional Web Security
Traditional web applications return rendered HTML, meaning security logic could often be embedded in view templates.
Modern REST and GraphQL APIs return raw JSON data to SPAs and mobile apps. The client decides how to display the data, meaning backend APIs must independently enforce every single authorization, filtering, and validation rule.
2. Mitigating BOLA (Broken Object Level Authorization)
BOLA occurs when an endpoint accepts an object identifier (such as `/api/users/1042/financials`) and fails to verify that the authenticated caller actually possesses permission to access record 1042.
Never trust user-supplied IDs. Always evaluate access control against the authenticated session token's verified identity.
// INSECURE: Relies on client-supplied ID without ownership check
app.get('/api/orders/:id', async (req, res) => {
const order = await db.orders.find(req.params.id);
return res.json(order);
});
// SECURE: Enforces tenant and ownership boundaries in the query
app.get('/api/orders/:id', authenticateToken, async (req, res) => {
const order = await db.orders.findFirst({
where: { id: req.params.id, userId: req.user.id },
});
if (!order) return res.status(404).json({ error: 'Order not found' });
return res.json(order);
});3. Preventing Mass Assignment Vulnerabilities
When developers use shorthand ORM functions like `User.update(req.body)`, a client can append administrative parameters (e.g. `"isAdmin": true` or `"tier": "enterprise"`).
Always implement Data Transfer Objects (DTOs) with strict allow-list schemas using libraries such as Zod, Joi, or Pydantic.
4. GraphQL Specific Protections
GraphQL enables clients to request arbitrary nested data. Malicious actors exploit this by crafting cyclic queries (`author -> posts -> author -> posts`) that consume 100% of server CPU.
Implement `graphql-depth-limit` and query cost analysis to reject queries exceeding safe complexity thresholds.