HIGH jwt misconfigurationexpressbasic auth

Jwt Misconfiguration in Express with Basic Auth

Jwt Misconfiguration in Express with Basic Auth — how this specific combination creates or exposes the vulnerability

JWT misconfiguration in an Express API that also uses HTTP Basic Authentication can create a layered risk where weaknesses in one mechanism weaken the other. Basic Authentication transmits a base64-encoded username:password pair in the Authorization header on every request; if transmitted over non-TLS transport, these credentials are easily exposed. Even when TLS is used, relying solely on Basic Auth without proper JWT validation can lead to authorization bypass (BOLA/IDOR) or over-privileged access.

Misconfigured JWT handling often involves missing or weak verification of signatures, acceptance of unsigned tokens (alg: none), or overly broad scopes/roles embedded in the token. When combined with Basic Auth, an attacker who intercepts or steals the Basic credentials gains a valid identity, and a misconfigured JWT validation layer may allow that identity to be elevated or impersonated across endpoints. For example, if the server decodes the JWT payload without verifying the issuer (iss) or audience (aud), and maps the Basic Auth username directly to a role in the token, an attacker can reuse Basic credentials with a tampered token to escalate privileges or access other users’ resources (BOLA/IDOR).

Another common pattern is using Basic Auth to retrieve a user record and then issuing a JWT that embeds permissions derived from that record. If token generation does not validate the scope of access and does not bind the token to the authenticated subject securely (e.g., missing or static jti, missing exp, or accepting tokens with overly long lifetimes), the JWT becomes a persistent bearer token. This is especially risky when endpoints inadvertently accept both Authorization: Basic and bearer tokens without strict scheme validation, leading to confused deputy scenarios where the wrong credential is trusted.

Specific OWASP API Top 10 risks amplified by this combination include Broken Object Level Authorization (BOLA/IDOR) when token claims do not enforce per-request ownership checks, and Security Misconfiguration through use of weak algorithms (none) or missing token binding. Because middleBrick tests authentication schemes and input validation in parallel, such misconfig surface quickly in scans, revealing missing signature verification, missing audience validation, or endpoints that process unsigned tokens.

Real-world attack patterns mirror known CVE behaviors: unsigned tokens (alg: none) allow attackers to forge admin claims; missing exp checks enable replay; and overly permissive scope mappings allow horizontal privilege escalation. These issues compound when Basic Auth credentials are used to derive roles without additional context checks, making token validation a single point of failure.

Basic Auth-Specific Remediation in Express — concrete code fixes

To secure Express APIs that use HTTP Basic Authentication alongside JWT handling, enforce strict transport security, validate and scope tokens independently of Basic credentials, and avoid direct mapping of Basic identities into token privileges without verification.

First, require HTTPS for all endpoints and ensure Basic credentials are never logged or exposed in error messages. Use middleware that rejects requests that do not present TLS; do not allow fallback to non-TLS routes.

Second, validate JWTs rigorously before using them for authorization. Use a well-audited library such as jsonwebtoken and verify signature, issuer, audience, and expiration on every request. Do not accept tokens with alg: none; explicitly specify allowed algorithms.

Third, decouple authorization decisions from the Basic identity. After verifying Basic credentials, fetch the user record and then check permissions against a policy engine or database rather than trusting claims derived from the Basic identity alone. Enforce per-request ownership checks to prevent BOLA/IDOR.

Below are concrete, working Express examples that demonstrate secure handling of Basic Auth and JWT verification.

const express = require('express');
const jwt = require('jsonwebtoken');
const basicAuth = require('basic-auth');
const httpsOnly = require('helmet').hsts;

const app = express();

// Enforce HTTPS in production; in development use a TLS terminator
app.use((req, res, next) => {
  if (process.env.NODE_ENV === 'production' && !req.secure) {
    return res.status(400).json({ error: 'TLS required' });
  }
  next();
});

// Strict JWT verification with algorithm and audience/issuer checks
function verifyJwt(token) {
  const publicKey = process.env.JWT_PUBLIC_KEY; // PEM string
  return jwt.verify(token, publicKey, {
    algorithms: ['RS256'],
    audience: 'https://api.example.com/',
    issuer: 'https://auth.example.com/',
  });
}

// Middleware: require and validate JWT before route handling
function requireJwt(req, res, next) {
  const authHeader = req.headers.authorization || '';
  const parts = authHeader.split(' ');
  if (parts.length !== 2 || parts[0].toLowerCase() !== 'bearer') {
    return res.status(401).json({ error: 'Authorization header must be Bearer ' });
  }
  try {
    const decoded = verifyJwt(parts[1]);
    req.user = decoded; // contains sub, scope, roles, jti, exp, etc.
    next();
  } catch (err) {
    return res.status(401).json({ error: 'Invalid token', details: err.message });
  }
}

// Middleware: validate Basic credentials and derive user context without mapping directly to JWT claims
function validateBasic(req, res, next) {
  const user = basicAuth(req);
  if (!user || !user.name || !user.pass) {
    res.set('WWW-Authenticate', 'Basic realm="API"');
    return res.status(401).json({ error: 'Basic credentials required' });
  }
  // Perform secure lookup (e.g., against a hashed password store)
  // Do NOT issue a JWT here based only on Basic identity; issue after full validation
  // Example placeholder: const dbUser = await db.findUserByUsername(user.name);
  const dbUser = { id: 'u-123', username: user.name, roles: ['user'] }; // simplified
  req.basicUser = dbUser;
  next();
}

// Example endpoint requiring both schemes: Basic for identification, JWT for authorization
app.get('/v1/profile', validateBasic, requireJwt, (req, res) => {
  // Ensure the JWT subject matches the Basic-identified user to prevent BOLA
  if (req.user.sub !== req.basicUser.id) {
    return res.status(403).json({ error: 'Subject mismatch: token does not match authenticated user' });
  }
  // Perform ownership/resource checks here before data access
  res.json({ profileId: req.user.sub, roles: req.user.roles || [] });
});

app.listen(3000, () => console.log('API listening on port 3000'));

Key points in the example:

  • TLS enforcement prevents Basic credentials from traversing the network in clear text.
  • JWT verification specifies RS256 and validates audience and issuer to prevent token substitution across realms.
  • Basic credentials are used to retrieve user context, but authorization decisions are based on verified JWT claims plus explicit ownership checks, avoiding direct role mapping from Basic identity.
  • The endpoint explicitly compares req.user.sub and req.basicUser.id to prevent BOLA/IDOR when tokens are used for authorization.

In continuous monitoring setups (Pro plan), such validation logic is exercised on each scan, and findings like missing token audience validation or missing TLS enforcement appear with remediation guidance. The GitHub Action can fail builds when risk scores exceed your defined thresholds, and the CLI can be integrated into scripts to enforce secure patterns before deployment.

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

Does Basic Auth over HTTPS prevent all risks associated with JWT misconfiguration?
No. Transmitting credentials over HTTPS protects confidentiality in transit, but it does not fix JWT-specific issues such as weak signing algorithms, missing audience/issuer validation, or lack of token binding. Always validate JWTs rigorously and enforce per-request authorization checks.
Should I accept both Basic Auth and JWT Bearer tokens on the same endpoint?
Avoid accepting both schemes on the same endpoint without strict separation. If both are supported, ensure the server validates each independently, does not implicitly trust one over the other, and enforces explicit scope and ownership checks to prevent confused deputy and BOLA/IDOR.