HIGH broken authenticationexpressbearer tokens

Broken Authentication in Express with Bearer Tokens

Broken Authentication in Express with Bearer Tokens — how this specific combination creates or exposes the vulnerability

Broken Authentication in Express when using Bearer Tokens typically arises from a combination of weak token handling, missing validation, and improper storage or transmission practices. When an API relies on Bearer Tokens without enforcing strict token lifecycle and transport controls, attackers can hijack or forge credentials to assume identities.

One common pattern is an Express route that reads req.headers.authorization and assumes a Bearer token is present and valid without verifying its signature, expiration, or scope. For example:

app.get('/profile', (req, res) => {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  const token = authHeader.split(' ')[1];
  // Vulnerable: no verification of token signature or claims
  res.json({ profile: 'user data' });
});

If the token is not cryptographically verified, an attacker can craft a valid-looking token or replay a stolen token. Without token binding or audience/issuer validation, the server cannot distinguish legitimate tokens from tampered ones.

Another vulnerability vector is token leakage in logs, URLs, or browser storage. For instance, passing tokens as URL query parameters exposes them in server logs and browser history:

GET /api/data?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...  

This practice increases the risk of token exposure through referrer headers or log aggregation systems. Additionally, failing to set the HttpOnly, Secure, and SameSite attributes on cookies that store tokens (if used in a cookie-based flow) can enable cross-site scripting (XSS) token theft.

Insecure token storage on the client side, such as storing tokens in localStorage, makes them accessible to JavaScript and susceptible to XSS. Without short expiration times and refresh token rotation, compromised tokens remain valid for extended periods, amplifying the impact of token leakage.

Broken Authentication in this context is not limited to missing signature checks. It also encompasses missing rate limiting on token validation endpoints, lack of proper token revocation mechanisms, and missing detection of anomalous token usage patterns. When combined with weak entropy in token generation, the attack surface grows significantly, enabling token prediction or brute-force attacks.

Finally, missing or misconfigured CORS policies can allow unauthorized origins to include bearer tokens in requests, leading to cross-origin credential leakage. Together, these factors make the Express + Bearer Token combination prone to session hijacking, privilege escalation, and unauthorized access when security controls are incomplete or inconsistently applied.

Bearer Tokens-Specific Remediation in Express — concrete code fixes

Remediation focuses on cryptographically verifying tokens, enforcing transport security, and minimizing exposure. Use a well-audited library such as jsonwebtoken to validate tokens, and enforce strict checks on issuer, audience, and expiration.

Here is a secure Express route example using Bearer Tokens with JWT verification:

const jwt = require('jsonwebtoken');

const PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----`;

function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];
  if (!token) {
    return res.status(401).json({ error: 'Access token required' });
  }
  jwt.verify(token, PUBLIC_KEY, { algorithms: ['RS256'], audience: 'api.example.com', issuer: 'https://auth.example.com/' }, (err, decoded) => {
    if (err) {
      return res.status(403).json({ error: 'Invalid or expired token' });
    }
    req.user = decoded;
    next();
  });
}

app.get('/profile', authenticateToken, (req, res) => {
  res.json({ profile: 'user data', user: req.user.sub });
});

Always specify the algorithm (e.g., RS256) to prevent algorithm confusion attacks. Validate the aud and iss claims to ensure the token was issued for your API and by a trusted identity provider.

Enforce HTTPS in production by using app.use((req, res, next) => { if (req.secure) next(); else res.status(400).send('HTTPS required'); }); or a load balancer-level redirect. Set short access token lifetimes (e.g., 15 minutes) and implement refresh token rotation with strict storage rules.

On the client side, store tokens in memory or in secure, HttpOnly cookies with Secure and SameSite=Strict flags rather than localStorage. If cookies are used, ensure CSRF protections are in place. Avoid URL parameters for tokens to prevent leakage in logs and browser history.

Add rate limiting on authentication endpoints to mitigate brute-force and token guessing attacks. Libraries such as express-rate-limit can be applied to sensitive routes:

const rateLimit = require('express-rate-limit');

const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,
  message: { error: 'Too many attempts, try again later' },
});

app.post('/login', authLimiter, (req, res) => {
  // handle credentials and issue tokens
});

Implement token revocation via a denylist (short-lived) or by rotating signing keys and maintaining a minimal validity window. Monitor for anomalous patterns such as multiple regions or IPs using the same token, and respond with token invalidation when suspicious activity is detected.

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

Why is verifying the token signature and claims important in Express?
Verifying the signature ensures the token was issued by a trusted party and has not been tampered with. Validating claims such as audience (aud) and issuer (iss) prevents tokens intended for other services from being accepted, reducing the risk of impersonation and cross-service abuse.
What are the risks of storing Bearer Tokens in localStorage?
Storing tokens in localStorage makes them accessible to malicious JavaScript, increasing the risk of theft via cross-site scripting (XSS). Prefer secure, HttpOnly cookies with appropriate SameSite and Secure flags, or keep tokens in memory, and always enforce HTTPS to protect tokens in transit.