HIGH broken authenticationexpressapi keys

Broken Authentication in Express with Api Keys

Broken Authentication in Express with Api Keys — how this specific combination creates or exposes the vulnerability

Broken Authentication occurs when application functions related to authentication and session management are implemented incorrectly, enabling attackers to compromise passwords, keys, or session tokens. In Express, using API keys for authentication can introduce authentication bypass or privilege escalation when keys are transmitted, stored, or validated insecurely.

API keys are often passed in HTTP headers (e.g., x-api-key). If an Express app does not enforce strict validation, transport security, and scope checks, attackers can exploit several weaknesses:

  • Keys transmitted over unencrypted HTTP, enabling network interception (CWE-319).
  • Missing or weak key binding to a specific scope or rate limits, enabling credential reuse or privilege escalation (CWE-287, CWE-613).
  • Hardcoded or leaked keys in client-side code, logs, or error messages, leading to unauthorized access (CWE-798).
  • Insufficient verification of key ownership before processing sensitive operations, enabling BOLA/IDOR-like access when keys are guessable or weakly namespaced.

Because middleBrick tests unauthenticated attack surfaces across 12 parallel checks including Authentication, BOLA/IDOR, and Property Authorization, these misconfigurations are detectable. For example, an endpoint that accepts an API key but does not verify whether the key’s associated permissions include the requested action can lead to privilege escalation — a pattern commonly flagged under BFLA and Property Authorization checks. Similarly, missing rate limiting on key-validated routes can enable brute-force attempts against weakly structured keys, aligning with Rate Limiting findings.

When scanning an Express API with middleBrick, findings may map to OWASP API Top 10:2023 (Broken Authentication), PCI-DSS requirements around secure authentication, and SOC2 controls related to identity and access management. The scanner also cross-references OpenAPI/Swagger definitions (2.0, 3.0, 3.1) with runtime behavior, so discrepancies between declared security schemes and actual enforcement are surfaced as actionable items with remediation guidance.

Api Keys-Specific Remediation in Express — concrete code fixes

To secure API keys in Express, enforce transport protection, strict validation, scope binding, and secure storage. Below are concrete, working code examples demonstrating these remediations.

1. Enforce HTTPS and validate the key on every request

Ensure all API key exchanges occur over TLS and validate the key against a secure store on each request. Do not rely on static or embedded keys in client code.

const express = require('express');
const https = require('https');
const fs = require('fs');

const app = express();

// Load server certificate and key for HTTPS
const options = {
  key: fs.readFileSync('/etc/ssl/private/server.key'),
  cert: fs.readFileSync('/etc/ssl/certs/server.crt')
};

// In-memory store for demo; use a secure database or secret manager in production
const validApiKeys = new Set([
  'sk_prod_abc123xyz',
  'sk_prod_456defuv'
]);

// Middleware to validate API key
app.use((req, res, next) => {
  const apiKey = req.header('x-api-key');
  if (!apiKey) {
    return res.status(401).json({ error: 'API key missing' });
  }
  if (!validApiKeys.has(apiKey)) {
    return res.status(403).json({ error: 'Invalid API key' });
  }
  // Attach key metadata for downstream use (e.g., scope, rate limits)
  req.apiKey = { key: apiKey, scope: 'read-write' };
  next();
});

app.get('/secure/data', (req, res) => {
  res.json({ message: 'Authenticated and authorized', data: 'sensitive' });
});

https.createServer(options, app).listen(443, () => {
  console.log('HTTPS server running on port 443');
});

2. Bind keys to scopes and enforce least privilege

Associate each key with a defined scope and validate that the scope permits the requested operation. This reduces the impact of a leaked key and aligns with Property Authorization checks.

const keyScopes = {
  'sk_prod_readonly': ['read:data'],
  'sk_prod_readwrite': ['read:data', 'write:data']
};

app.use((req, res, next) => {
  const apiKey = req.header('x-api-key');
  const keyMeta = keyScopes[apiKey];
  if (!keyMeta) {
    return res.status(403).json({ error: 'Forbidden scope or invalid key' });
  }
  req.keyScopes = keyMeta;
  next();
});

app.post('/secure/data', (req, res) => {
  if (!req.keyScopes.includes('write:data')) {
    return res.status(403).json({ error: 'Insufficient scope for write' });
  }
  res.json({ message: 'Write operation authorized' });
});

3. Apply rate limiting per key to mitigate brute-force and abuse

Use a sliding window or token bucket approach to limit requests per API key. This complements Authentication and Rate Limiting checks flagged by middleBrick.

const rateLimit = new Map();

app.use((req, res, next) => {
  const apiKey = req.header('x-api-key');
  const now = Date.now();
  const windowMs = 60_000; // 1 minute
  const maxRequests = 100;

  if (!rateLimit.has(apiKey)) {
    rateLimit.set(apiKey, { count: 1, start: now });
    return next();
  }

  const record = rateLimit.get(apiKey);
  if (now - record.start > windowMs) {
    record.count = 1;
    record.start = now;
  } else {
    record.count += 1;
  }

  if (record.count > maxRequests) {
    return res.status(429).json({ error: 'Rate limit exceeded' });
  }
  next();
});

4. Avoid exposing keys in logs, errors, or client-side code

Sanitize outputs and ensure API keys never appear in logs or error traces. Never send keys in URLs or response bodies.

app.use((err, req, res, next) => {
  // Ensure key is not included in error logs
  console.error('Request failed:', { path: req.path, method: req.method, error: err.message });
  res.status(500).json({ error: 'Internal server error' });
});

By combining HTTPS enforcement, strict key validation, scope binding, and rate limiting, Express applications can significantly reduce the risk of Broken Authentication when using API keys. middleBrick’s checks for Authentication, BOLA/IDOR, Property Authorization, and Rate Limiting help identify residual risks, and its integrations with the Dashboard, CLI, and GitHub Action support continuous monitoring of these controls.

Related CWEs: authentication

CWE IDNameSeverity
CWE-287Improper Authentication CRITICAL
CWE-306Missing Authentication for Critical Function CRITICAL
CWE-307Brute Force HIGH
CWE-308Single-Factor Authentication MEDIUM
CWE-309Use of Password System for Primary Authentication MEDIUM
CWE-347Improper Verification of Cryptographic Signature HIGH
CWE-384Session Fixation HIGH
CWE-521Weak Password Requirements MEDIUM
CWE-613Insufficient Session Expiration MEDIUM
CWE-640Weak Password Recovery HIGH

Frequently Asked Questions

Can API keys alone replace sessions or OAuth for authentication in Express?
API keys can identify services or applications, but they typically lack user-level identity and revocation controls required for session or OAuth-based authentication. Use API keys for service-to-service auth with strict scope and rotation; combine with other mechanisms for user authentication.
How often should I rotate API keys in an Express service?
Rotate keys on a regular schedule (e.g., monthly) and immediately if a leak is suspected. Automated rotation integrated with secure secret stores reduces exposure and aligns with continuous monitoring practices supported by middleBrick’s scanning and alerting.