Skip to content

Services, Wiki-Artikel, Blog-Beiträge und Glossar-Einträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen
Web-Sicherheit Glossary

API-Sicherheit

Protecting APIs (Application Programming Interfaces) against misuse, unauthorized access, injection attacks, and data leaks. APIs are a modern attack surface: The OWASP API Security Top 10 lists the most common vulnerabilities, ranging from Broken Object-Level Authorization to Rate Limiting.

API security has become a distinct discipline in modern software development. While traditional web security focused on HTML pages, 83% of web applications today communicate primarily via APIs (Akamai State of the Internet 2024).

OWASP API Security Top 10

OWASP has a separate Top 10 list for API security:

API1: Broken Object Level Authorization (BOLA/IDOR)

// Insecure: No owner check
GET /api/orders/4891
// → Attacker changes ID: GET /api/orders/4892 → third-party order visible

// Secure:
app.get('/api/orders/:id', authenticate, async (req, res) => {
  const order = await Order.findOne({
    _id: req.params.id,
    userId: req.user.id  // Owner check!
  });
  if (!order) return res.status(404).send();
  res.json(order);
});

API2: Broken Authentication

// Dangerous: Weak JWT algorithm
// Header: {"alg": "none", "typ": "JWT"}
// → The "none" algorithm accepts any token without signature verification!

// Secure: Explicitly specify the algorithm
const token = jwt.verify(req.headers.authorization, process.env.JWT_SECRET, {
  algorithms: ['HS256'],  // Only accept HS256!
  expiresIn: '1h'
});

API3: Broken Object Property Level Authorization

// Insecure: Mass Assignment
app.put('/api/user', authenticate, async (req, res) => {
  await User.findByIdAndUpdate(req.user.id, req.body);  // Attacker sets isAdmin: true!
});

// Secure: Only allowed fields
const { name, email } = req.body;
await User.findByIdAndUpdate(req.user.id, { name, email });  // isAdmin not possible

API4: Unrestricted Resource Consumption

Without rate limiting:

  • Attacker sends 10,000 requests/second
  • API costs skyrocket (AWS Lambda, OpenAI API)
  • DoS for other users
  • Brute-force attacks possible

API5: Broken Function-Level Authorization

// Insecure: Admin endpoint without admin check
app.delete('/api/admin/users/:id', authenticate, async (req, res) => {
  await User.findByIdAndDelete(req.params.id);  // No admin check!
});

// Secure:
app.delete('/api/admin/users/:id', authenticate, requireAdmin, async (req, res) => {
  // requireAdmin middleware checks req.user.role === 'admin'
  await User.findByIdAndDelete(req.params.id);
});

API Authentication Best Practices

API Keys

Not suitable for user authentication:

  • API keys are shared secrets
  • Cannot be revoked without updating all clients
  • No scoping (granular permissions are difficult)

Good for: Server-to-server communication, service accounts

Best Practices:

  • API key in the header: Authorization: Bearer sk_live_abc123...
  • NEVER in the URL: ?api_key=abc123 (ends up in logs!)
  • Separate keys per environment (Dev/Staging/Prod)
  • Enable rotation

OAuth 2.0 + OIDC

Modern framework for API authorization:

  • Tokens (Access Token, Refresh Token)
  • Scopes: Granular permissions (read:orders, write:orders)
  • Token Expiry: Short lifespan (15-minute access tokens)
  • Revocation: Revoke tokens if compromised

PKCE for Single Page Apps (prevents Authorization Code Interception):

  • Code Verifier + Code Challenge
  • Secure even without a client secret

JWT Security

// JWT Best Practices:
const token = jwt.sign(
  {
    userId: user.id,
    role: user.role,
    // NOT: Password, sensitive data (JWT is base64-decodable!)
  },
  process.env.JWT_SECRET,  // From environment variable, never hardcoded
  {
    expiresIn: '15m',      // Short lifetime
    issuer: 'api.company.com',
    audience: 'api.company.com',
    algorithm: 'HS256'     // Specify explicitly
  }
);

// Validation:
const decoded = jwt.verify(token, process.env.JWT_SECRET, {
  algorithms: ['HS256'],  // 'none' is not allowed!
  issuer: 'api.company.com',
  audience: 'api.company.com'
});

API Rate Limiting

// Express Rate Limiter
const rateLimit = require('express-rate-limit');

const apiLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,  // 15 minutes
  max: 100,                   // 100 requests per IP
  message: 'Too many requests, please try again later.',
  standardHeaders: true,      // X-RateLimit-* headers
  legacyHeaders: false,
});

app.use('/api/', apiLimiter);

// Stricter for authentication:
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,  // Only 5 login attempts
  skipSuccessfulRequests: true,  // Only failed attempts count
});
app.use('/api/auth/login', authLimiter);

API Security Testing

For penetration testing or DAST

Tools for API penetration testing:

ToolPurpose
Burp Suite ProIntercepting proxy + scanner + repeater
PostmanManual testing, collection runs
OWASP ZAPAutomatic API scan
ArjunParameter discovery
ffufEndpoint fuzzing

Important Tests:

  • IDOR: Try all IDs (1, 2, 3, ...)
  • Auth Bypass: Omit token, use old token, use third-party token
  • Method Tampering: GET instead of POST, HEAD instead of GET
  • Verbose Error Messages: Does the API return stack traces?
  • Mass Assignment: Send extra fields in the request body

API Security Headers

# Recommended headers for APIs:
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "DENY";
add_header Referrer-Policy "no-referrer";
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()";

# Configure CORS correctly:
# DO NOT: Access-Control-Allow-Origin: *
# Instead:
Access-Control-Allow-Origin: https://app.firma.de
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization, Content-Type