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 ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |