API Bezbednost — Vodic za zastitu
Objavljeno: 8. april 2026. · Vreme citanja: 16 min
Sadrzaj
1. Zasto je API bezbednost kriticna
API-ji (Application Programming Interfaces) su postali kicma modernih aplikacija. Mobilne aplikacije, single-page web aplikacije, IoT uredjaji, i mikroservisi — svi komuniciraju putem API-ja. To znaci da su API-ji postali primarna meta napadaca.
Za razliku od tradicionalnih web aplikacija gde je logika na serveru, API-ji izlazu poslovnu logiku direktno. Ako API endpoint dozvolava korisniku da pristupi tudjim podacima samo promenom ID-ja u URL-u, to je kriticna ranjivost.
2. OWASP API Security Top 10 (2023)
OWASP (Open Web Application Security Project) je 2023. godine objavio azuriranu listu 10 najkriticnijih API bezbednosnih rizika:
API1:2023 — Broken Object Level Authorization (BOLA)
Najcesci API rizik. Korisnik moze pristupiti objektima drugih korisnika menjajuci ID u zahtevu. Primer: GET /api/users/123/orders — sta se desava ako promenite 123 na 456?
# Ranjiv endpoint — nema provere vlasnistva
GET /api/invoices/1001 # Korisnik A vidi svoju fakturu
GET /api/invoices/1002 # Korisnik A vidi fakturu korisnika B!
# Ispravan pristup — uvek proveravajte vlasnistvo
app.get('/api/invoices/:id', auth, async (req, res) => {
const invoice = await Invoice.findById(req.params.id);
if (invoice.userId !== req.user.id) {
return res.status(403).json({ error: 'Forbidden' });
}
res.json(invoice);
});
API2:2023 — Broken Authentication
Slabi mehanizmi autentifikacije: nedostatak rate limiting-a na login, slabi tokeni, nezasticeni API kljucevi u kodu, ili nedostatak token expiration-a.
API3:2023 — Broken Object Property Level Authorization
Korisnik moze da cita ili modifikuje svojstva objekta koja ne bi trebalo. Primer: korisnik salje PUT zahtev i menja polje "role": "admin" u svom profilu (mass assignment).
API4:2023 — Unrestricted Resource Consumption
API nema ogranicenja na resurse: bez rate limiting-a, bez limita na velicinu payloada, bez ogranicenja na kompleksnost upita. Ovo vodi ka DoS napadima.
API5:2023 — Broken Function Level Authorization
Obican korisnik moze pristupiti admin endpoint-ima. Primer: POST /api/admin/users/delete je dostupan i obicnim korisnicima.
API6:2023 — Unrestricted Access to Sensitive Business Flows
Automatizovano zloupotrebljavanje poslovnih tokova: masovna kupovina limitiranih proizvoda, automatsko kreiranje naloga, scraping podataka.
API7:2023 — Server Side Request Forgery (SSRF)
API prihvata URL od korisnika i vrsi zahtev ka tom URL-u bez validacije. Napadac moze pristupiti internim servisima (metadata endpoint, interne baze).
API8:2023 — Security Misconfiguration
Nebezbedna podrazumevana konfiguracija: otvoren CORS, verbose error poruke, nepotrebni HTTP metodi, stare TLS verzije.
API9:2023 — Improper Inventory Management
Stare verzije API-ja ostaju aktivne i nezasticene. Shadow API-ji koje tim ne zna da postoje. Nedokumentovani endpoint-i.
API10:2023 — Unsafe Consumption of APIs
Aplikacija veruje odgovorima od third-party API-ja bez validacije. Ako provajder bude kompromitovan, vas API takodje postaje ranjiv.
3. Autentifikacija: API Keys vs OAuth 2.0 vs JWT
| Metoda | Prednosti | Mane | Kada koristiti |
|---|---|---|---|
| API Keys | Jednostavno, brzo za implementaciju | Nema user context, tesko za rotaciju, cesto leakuju | Server-to-server, javni API-ji sa ogranicenjem |
| OAuth 2.0 | Standardizovano, delegirana autorizacija, scopes | Kompleksno za implementaciju, mnogi flow-ovi | Third-party pristup, korisnicka autorizacija |
| JWT | Stateless, sadrzi claims, efikasno | Ne moze se revocirati bez blackliste, payload vidljiv | Mikroservisi, SPA autentifikacija |
4. JWT bezbednost
JWT (JSON Web Token, definisan u RFC 7519) se sastoji od tri dela: Header, Payload, i Signature, razdvojenih tackama.
# JWT struktura
eyJhbGciOiJSUzI1NiJ9. # Header: {"alg":"RS256"}
eyJ1c2VyIjoiam9obiJ9. # Payload: {"user":"john"}
SflKxwRJSMeKKF2QT4fw... # Signature
# OPASNO: "none" algoritam napad
# Napadac menja header na {"alg":"none"} i uklanja potpis
eyJhbGciOiJub25lIn0.eyJ1c2VyIjoiYWRtaW4ifQ.
# Neki serveri prihvataju ovo kao validan token!
JWT bezbednosne preporuke
- Uvek validirajte algoritam — eksplicitno navedite dozvoljene algoritme, nikada ne prihvatajte
"alg": "none" - Koristite asimetricne algoritme — RS256 ili ES256 umesto HS256 kada vise servisa verifikuje tokene
- Kratko vreme isteka — pristupni tokeni: 15-30 minuta, refresh tokeni: 7-30 dana
- Proveravajte
exp,iss,audclaims — ne samo potpis - Cuvajte tajnu kljuca — nikada u kodu, koristite environment varijable ili vault
// Node.js — bezbedna JWT verifikacija
const jwt = require('jsonwebtoken');
function verifyToken(token) {
try {
// Eksplicitno navedite dozvoljeni algoritam
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'], // Samo RS256!
issuer: 'https://auth.mojsajt.rs',
audience: 'https://api.mojsajt.rs',
clockTolerance: 30 // 30 sekundi tolerancije
});
return decoded;
} catch (err) {
throw new Error('Invalid token: ' + err.message);
}
}
5. GraphQL specificni rizici
Introspection u produkciji
GraphQL introspection omogucava klijentu da upita kompletnu semu API-ja. U razvoju je korisno, ali u produkciji otkriva sve tipove, polja, relacije i mutacije napadacu.
# Introspection upit koji otkriva celu semu
{
__schema {
types {
name
fields {
name
type { name }
}
}
}
}
# Iskljucite introspection u produkciji (Apollo Server)
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: process.env.NODE_ENV !== 'production',
});
Depth limiting
Bez ogranicenja dubine, napadac moze poslati duboko ugnjezden upit koji preopterecuje server:
# Maliciozni upit sa preteranom dubinom
{
user(id: 1) {
friends {
friends {
friends {
friends {
friends { name } # N nivoa dubine = eksponencijalna slozenost
}
}
}
}
}
}
# Zastita: koristite graphql-depth-limit
const depthLimit = require('graphql-depth-limit');
const server = new ApolloServer({
validationRules: [depthLimit(5)]
});
Batching napadi
GraphQL dozvoljava slanje vise upita u jednom zahtevu. Napadac moze poslati stotine login pokusaja u jednom HTTP zahtevu, zaobilazeci rate limiting koji se oslanja na broj HTTP zahteva.
6. Rate limiting implementacija
// Express.js rate limiting sa express-rate-limit
const rateLimit = require('express-rate-limit');
// Globalni limiter
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minuta
max: 100, // 100 zahteva po windowMs
standardHeaders: true,
legacyHeaders: false,
message: { error: 'Too many requests, try again later' }
});
// Strozi limiter za login
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5, // Samo 5 pokusaja logina na 15 min
skipSuccessfulRequests: true
});
app.use('/api/', apiLimiter);
app.use('/api/auth/login', loginLimiter);
// Nginx rate limiting konfiguracija
// limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
// location /api/ {
// limit_req zone=api burst=20 nodelay;
// }
7. Swagger/OpenAPI u produkciji
Swagger UI i OpenAPI specifikacija su odlicni za razvoj, ali u produkciji mogu otkriti kompletnu strukturu API-ja napadacu:
/swagger, /api-docs, ili /openapi.json endpoint daje napadacu mapu svih endpoint-ova, parametara, i modela podataka. Uvek ga iskljucite ili zastitite autentifikacijom u produkciji.
// Express.js — uslovni Swagger pristup
if (process.env.NODE_ENV !== 'production') {
const swaggerUi = require('swagger-ui-express');
const swaggerDoc = require('./swagger.json');
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDoc));
}
// Ili zastitite autentifikacijom
app.use('/api-docs', basicAuth({
users: { 'admin': process.env.SWAGGER_PASSWORD },
challenge: true
}), swaggerUi.serve, swaggerUi.setup(swaggerDoc));
8. Realni primeri API breach-eva
Facebook API breach (septembar 2018)
Napadaci su eksploatisali ranjivost u Facebook-ovom "View As" feature-u koji je koristio API za generisanje pristupnih tokena. Ranjivost je omogucila kradju pristupnih tokena za 50 miliona korisnickih naloga. Facebook je bio prisiljen da resetuje tokene za 90 miliona korisnika.
Izvor: Facebook Security Update, septembar 2018; FTC Settlement, 2019
Peloton API (maj 2021)
Istrazivac bezbednosti Jan Masters je otkrio da je Peloton API dozvoljavao neautentifikovanim korisnicima da pristupe privatnim korisnickim podacima — ukljucujuci starost, pol, grad, tezinu, i istoriju treninga. API nije proveravao autorizaciju na endpoint-ima za korisnicke profile.
Izvor: TechCrunch, "Peloton's leaky API let anyone grab riders' private account data", maj 2021
T-Mobile API breach (avgust 2021)
Napadac je otkrio nezasticen API endpoint koji je izlagao podatke 40+ miliona korisnika ukljucujuci imena, datume rodjenja, SSN brojeve i vozacke dozvole. Napadac John Binns je tvrdio da je "njihova bezbednost uzasna".
Izvor: T-Mobile Data Breach Notice, avgust 2021
9. Cesto postavljana pitanja
O: API key sam po sebi je samo identifikator, ne autentifikacija. Ne sadrzi informacije o korisniku, tesko se rotira, i cesto leakuje u javne Git repozitorijume. Za korisnicku autentifikaciju koristite OAuth 2.0 ili JWT.
O: HttpOnly Secure cookie je najbezbednija opcija jer nije dostupan JavaScript-u (zastita od XSS). LocalStorage je ranjiv na XSS napade. Nikada ne cuvajte tokene u URL parametrima.
O: Kombinujte rate limiting, CAPTCHA za sumnjive aktivnosti, fingerprinting korisnika, i honeypot endpoint-e. Nijedna mera sama nije dovoljna.
10. Reference
- OWASP API Security Top 10 (2023)
- RFC 6749 — OAuth 2.0 Authorization Framework
- RFC 7519 — JSON Web Token (JWT)
- Salt Security: State of API Security Report 2023
- PortSwigger: JWT Attacks
- IBM Cost of a Data Breach Report 2023
API Security — Protection Guide
Published: April 8, 2026 · Reading time: 16 min
Table of Contents
1. Why API security is critical
APIs (Application Programming Interfaces) have become the backbone of modern applications. Mobile apps, single-page web applications, IoT devices, and microservices all communicate via APIs. This means APIs have become a primary target for attackers.
Unlike traditional web applications where logic lives on the server, APIs expose business logic directly. If an API endpoint allows a user to access another user's data simply by changing the ID in the URL, that is a critical vulnerability.
2. OWASP API Security Top 10 (2023)
OWASP (Open Web Application Security Project) published the updated list of 10 most critical API security risks in 2023:
API1:2023 — Broken Object Level Authorization (BOLA)
The most common API risk. A user can access other users' objects by changing the ID in the request. Example: GET /api/users/123/orders — what happens if you change 123 to 456?
# Vulnerable endpoint — no ownership check
GET /api/invoices/1001 # User A sees their invoice
GET /api/invoices/1002 # User A sees User B's invoice!
# Correct approach — always check ownership
app.get('/api/invoices/:id', auth, async (req, res) => {
const invoice = await Invoice.findById(req.params.id);
if (invoice.userId !== req.user.id) {
return res.status(403).json({ error: 'Forbidden' });
}
res.json(invoice);
});
API2:2023 — Broken Authentication
Weak authentication mechanisms: lack of rate limiting on login, weak tokens, unprotected API keys in code, or missing token expiration.
API3:2023 — Broken Object Property Level Authorization
A user can read or modify object properties they shouldn't. Example: a user sends a PUT request and changes the "role": "admin" field in their profile (mass assignment).
API4:2023 — Unrestricted Resource Consumption
API has no resource limits: no rate limiting, no payload size limits, no query complexity restrictions. This leads to DoS attacks.
API5:2023 — Broken Function Level Authorization
Regular users can access admin endpoints. Example: POST /api/admin/users/delete is accessible to regular users.
API6:2023 — Unrestricted Access to Sensitive Business Flows
Automated abuse of business flows: mass purchasing of limited products, automated account creation, data scraping.
API7:2023 — Server Side Request Forgery (SSRF)
API accepts a URL from the user and makes a request to that URL without validation. Attacker can access internal services (metadata endpoint, internal databases).
API8:2023 — Security Misconfiguration
Insecure default configuration: open CORS, verbose error messages, unnecessary HTTP methods, old TLS versions.
API9:2023 — Improper Inventory Management
Old API versions remain active and unprotected. Shadow APIs that the team doesn't know exist. Undocumented endpoints.
API10:2023 — Unsafe Consumption of APIs
Application trusts responses from third-party APIs without validation. If the provider is compromised, your API also becomes vulnerable.
3. Authentication: API Keys vs OAuth 2.0 vs JWT
| Method | Pros | Cons | When to use |
|---|---|---|---|
| API Keys | Simple, quick to implement | No user context, hard to rotate, often leak | Server-to-server, public APIs with limits |
| OAuth 2.0 | Standardized, delegated authorization, scopes | Complex to implement, many flows | Third-party access, user authorization |
| JWT | Stateless, contains claims, efficient | Cannot revoke without blacklist, payload visible | Microservices, SPA authentication |
4. JWT security
JWT (JSON Web Token, defined in RFC 7519) consists of three parts: Header, Payload, and Signature, separated by dots.
# JWT structure
eyJhbGciOiJSUzI1NiJ9. # Header: {"alg":"RS256"}
eyJ1c2VyIjoiam9obiJ9. # Payload: {"user":"john"}
SflKxwRJSMeKKF2QT4fw... # Signature
# DANGEROUS: "none" algorithm attack
# Attacker changes header to {"alg":"none"} and removes signature
eyJhbGciOiJub25lIn0.eyJ1c2VyIjoiYWRtaW4ifQ.
# Some servers accept this as a valid token!
JWT security recommendations
- Always validate the algorithm — explicitly specify allowed algorithms, never accept
"alg": "none" - Use asymmetric algorithms — RS256 or ES256 instead of HS256 when multiple services verify tokens
- Short expiration time — access tokens: 15-30 minutes, refresh tokens: 7-30 days
- Check
exp,iss,audclaims — not just the signature - Protect the secret key — never in code, use environment variables or vault
// Node.js — secure JWT verification
const jwt = require('jsonwebtoken');
function verifyToken(token) {
try {
// Explicitly specify the allowed algorithm
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'], // Only RS256!
issuer: 'https://auth.mysite.com',
audience: 'https://api.mysite.com',
clockTolerance: 30 // 30 seconds tolerance
});
return decoded;
} catch (err) {
throw new Error('Invalid token: ' + err.message);
}
}
5. GraphQL specific risks
Introspection in production
GraphQL introspection allows a client to query the complete API schema. Useful in development, but in production it reveals all types, fields, relationships, and mutations to an attacker.
# Introspection query that reveals the entire schema
{
__schema {
types {
name
fields {
name
type { name }
}
}
}
}
# Disable introspection in production (Apollo Server)
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: process.env.NODE_ENV !== 'production',
});
Depth limiting
Without depth limits, an attacker can send a deeply nested query that overwhelms the server:
# Malicious query with excessive depth
{
user(id: 1) {
friends {
friends {
friends {
friends {
friends { name } # N levels deep = exponential complexity
}
}
}
}
}
}
# Protection: use graphql-depth-limit
const depthLimit = require('graphql-depth-limit');
const server = new ApolloServer({
validationRules: [depthLimit(5)]
});
Batching attacks
GraphQL allows sending multiple queries in a single request. An attacker can send hundreds of login attempts in one HTTP request, bypassing rate limiting that relies on HTTP request count.
6. Rate limiting implementation
// Express.js rate limiting with express-rate-limit
const rateLimit = require('express-rate-limit');
// Global limiter
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // 100 requests per windowMs
standardHeaders: true,
legacyHeaders: false,
message: { error: 'Too many requests, try again later' }
});
// Stricter limiter for login
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5, // Only 5 login attempts per 15 min
skipSuccessfulRequests: true
});
app.use('/api/', apiLimiter);
app.use('/api/auth/login', loginLimiter);
// Nginx rate limiting configuration
// limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
// location /api/ {
// limit_req zone=api burst=20 nodelay;
// }
7. Swagger/OpenAPI in production
Swagger UI and OpenAPI specification are great for development, but in production they can reveal the complete API structure to an attacker:
/swagger, /api-docs, or /openapi.json endpoint gives an attacker a map of all endpoints, parameters, and data models. Always disable or protect it with authentication in production.
// Express.js — conditional Swagger access
if (process.env.NODE_ENV !== 'production') {
const swaggerUi = require('swagger-ui-express');
const swaggerDoc = require('./swagger.json');
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDoc));
}
// Or protect with authentication
app.use('/api-docs', basicAuth({
users: { 'admin': process.env.SWAGGER_PASSWORD },
challenge: true
}), swaggerUi.serve, swaggerUi.setup(swaggerDoc));
8. Real-world API breach examples
Facebook API breach (September 2018)
Attackers exploited a vulnerability in Facebook's "View As" feature which used an API to generate access tokens. The vulnerability enabled theft of access tokens for 50 million user accounts. Facebook was forced to reset tokens for 90 million users.
Source: Facebook Security Update, September 2018; FTC Settlement, 2019
Peloton API (May 2021)
Security researcher Jan Masters discovered that Peloton's API allowed unauthenticated users to access private user data — including age, gender, city, weight, and workout history. The API did not check authorization on user profile endpoints.
Source: TechCrunch, "Peloton's leaky API let anyone grab riders' private account data", May 2021
T-Mobile API breach (August 2021)
An attacker discovered an unprotected API endpoint exposing data of 40+ million customers including names, dates of birth, SSN numbers, and driver's licenses. Attacker John Binns claimed "their security is awful."
Source: T-Mobile Data Breach Notice, August 2021
9. Frequently asked questions
A: An API key by itself is just an identifier, not authentication. It contains no user information, is hard to rotate, and often leaks into public Git repositories. For user authentication, use OAuth 2.0 or JWT.
A: An HttpOnly Secure cookie is the safest option because it is not accessible to JavaScript (XSS protection). LocalStorage is vulnerable to XSS attacks. Never store tokens in URL parameters.
A: Combine rate limiting, CAPTCHA for suspicious activity, user fingerprinting, and honeypot endpoints. No single measure is sufficient on its own.
10. References
- OWASP API Security Top 10 (2023)
- RFC 6749 — OAuth 2.0 Authorization Framework
- RFC 7519 — JSON Web Token (JWT)
- Salt Security: State of API Security Report 2023
- PortSwigger: JWT Attacks
- IBM Cost of a Data Breach Report 2023