API Security Overview
The OWASP API Security Top 10: BOLA, broken auth, excessive data exposure, mass assignment, and rate limiting. How APIs differ from browser-based apps — no session, no CSRF token, no trust boundary at the HTTP level.
The OWASP API Security Top 10: BOLA, broken auth, excessive data exposure, mass assignment, and rate limiting. How APIs differ from browser-based apps — no session, no CSRF token, no trust boundary at the HTTP level.
APIs are the connective tissue of modern applications. Mobile apps, single-page applications, IoT devices, and microservices all speak API - and each one is a potential entry point. Unlike browser-based apps with session cookies and Same-origin Policy, APIs rely on tokens, keys, and headers that attackers can forge, replay, or simply omit.
Traditional web applications benefit from browser-enforced security boundaries. Cookies are automatically scoped to the origin, the Same-origin Policy prevents cross-site reads, and Content Security Policy restricts script execution. APIs have none of these. An API is a programmatic interface - every request is made by code, and that code can come from anywhere. The authentication token is just a string, and if the API does not validate it correctly, or does not check whether the token holder is allowed to access the specific resource, the data is exposed.
The OWASP API Security Top 10 catalogues the most common and impactful API vulnerabilities. The top three alone account for the majority of real-world API breaches:
/api/users/123) without verifying that the current user owns that object. The attacker simply changes the ID.passwordHash, ssn, or internalNotes.role: "admin" or isAdmin: true.The attack surface also varies by API style. REST APIs expose resources through URL paths and HTTP methods - each endpoint is a potential target. GraphQL APIs consolidate data access into a single endpoint, but expose the full schema through introspection, letting attackers query any field. RPC-based APIs (like gRPC or JSON-RPC) often expose internal method names and may skip HTTP-level security controls entirely.
Use the API Playground below to explore how BOLA and excessive data exposure work in practice. Send requests as an authenticated user and try changing the user ID in REST URLs or GraphQL queries to access data you should not have permission to see.
In March 2021, security researcher David Paulovsky discovered that Peloton's API exposed any user's private profile data through a simple IDOR (Insecure Direct Object Reference) - a textbook BOLA vulnerability (OWASP API #1). The Peloton mobile app called an API endpoint like /api/user/123456/profile to display profile information. The API checked that the request carried a valid authentication token but never verified that the token belonged to the user whose profile was being requested.
An attacker could create a free Peloton account, capture their own auth token, and then iterate through user IDs to scrape private data including full name, age, weight, workout history, and location. The vulnerability affected millions of users. Peloton fixed it by enforcing object-level authorisation - the API now verifies that the authenticated user is the owner of the requested profile before returning any data.
The Peloton case is a classic example of a broken authorisation model: the API trusted that the authenticated user was requesting their own data simply because they had a valid token. Authentication (who are you?) is not the same as authorisation (are you allowed to do that?). BOLA happens when an API conflates the two.
Defending against the OWASP API Top 10 requires a layered approach that starts at the API design phase and continues through deployment:
// VULNERABLE — BOLA via direct object reference
app.get('/api/users/:id', (req, res) => {
const user = db.users.find(req.params.id);
res.json(user); // no ownership check
});
// SAFE — object-level authorisation
app.get('/api/users/:id', (req, res) => {
const user = db.users.find(req.params.id);
if (user.id !== req.auth.userId && req.auth.role !== 'admin') {
return res.status(403).json({ error: 'Forbidden' });
}
res.json(toViewModel(user)); // strip sensitive fields
});
// SAFE — rate limiting middleware
const limiter = rateLimit({
windowMs: 60_000, max: 100,
keyGenerator: (req) => req.ip,
});
app.use('/api/', limiter);
// SAFE — mass assignment prevention
const safeFields = ['username', 'email', 'avatarUrl'];
const update: Record<string, unknown> = {};
for (const field of safeFields) {
if (body[field] !== undefined) update[field] = body[field];
}
db.users.update(req.auth.userId, update);Key mitigation strategies include: always enforce object-level authorisation checks in the handler, never return full database entities directly (use a view-model or a projection), implement rate limiting on every public endpoint, whitelist bindable fields instead of using blanket deserialisation, and disable GraphQL introspection in production.
1.What is the difference between authentication and authorisation in the context of APIs?
2.Which OWASP API Security Top 10 category does the Peloton 2021 vulnerability fall under?
3.How does mass assignment (API #6) differ from excessive data exposure (API #3)?