HIGH broken authenticationexpress

Broken Authentication in Express

How Broken Authentication Manifests in Express

Broken authentication in Express applications often stems from improper session management and flawed credential handling. Express's default session middleware uses insecure cookie configurations by default, creating immediate vulnerabilities. When developers use express-session without setting secure: true, httpOnly: true, or sameSite: 'strict', session cookies become susceptible to interception and cross-site request forgery attacks.

A common Express-specific pattern that leads to broken authentication involves improper middleware ordering. If authentication middleware is placed after route handlers that should be protected, attackers can bypass authentication entirely. For example:

app.get('/admin', (req, res) => { // Vulnerable: no auth check
  res.json(adminData);
});
app.use(authenticate); // Too late!

This ordering allows unauthenticated access to sensitive endpoints. Express developers also frequently mishandle passport.js strategies, leaving authentication incomplete. A typical mistake is failing to check req.isAuthenticated() in protected routes:

app.get('/profile', (req, res) => {
  if (!req.user) { // Missing this check is catastrophic
    return res.status(401).json({error: 'Unauthorized'});
  }
  res.json(req.user);
});

Session fixation attacks are particularly effective against Express apps that don't regenerate session IDs after login. Attackers can pre-generate valid session cookies and force victims to use them, maintaining persistent access even after password changes.

Express-Specific Detection

Detecting broken authentication in Express requires examining both configuration and runtime behavior. Start by inspecting your package.json for outdated authentication dependencies like express-session or passport. Version 1.17.1 of express-session had a critical vulnerability allowing session fixation through predictable session IDs.

middleBrick's Express-specific scanning identifies broken authentication through several automated checks. The scanner tests for default session configurations, attempting to establish sessions without credentials. It examines cookie attributes, looking for missing secure flags or httpOnly settings that expose sessions to client-side JavaScript.

The scanner also performs credential stuffing detection by testing common weak passwords against authentication endpoints. For Express applications using JWTs, middleBrick checks for weak signing secrets and improper token validation. The scanner can identify endpoints that accept expired tokens or fail to validate token structure properly.

npm install -g middlebrick
middlebrick scan https://yourapi.com --output json

This command returns a detailed report showing authentication vulnerabilities specific to your Express setup. The report includes severity ratings and references to OWASP API Top 10 categories like 'Broken Authentication' and 'Insufficient Logging & Monitoring'.

Express-Specific Remediation

Fixing broken authentication in Express requires implementing defense-in-depth strategies. Start with proper session configuration:

const session = require('express-session');
const MongoStore = require('connect-mongo');

app.use(session({
  secret: process.env.SESSION_SECRET || crypto.randomBytes(32).toString('hex'),
  store: MongoStore.create({ mongoUrl: process.env.MONGO_URI }),
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: process.env.NODE_ENV === 'production',
    httpOnly: true,
    sameSite: 'strict',
    maxAge: 24 * 60 * 60 * 1000 // 24 hours
  }
}));

Always regenerate session IDs upon authentication state changes to prevent fixation attacks:

app.post('/login', async (req, res) => {
  const user = await User.authenticate(req.body.email, req.body.password);
  if (!user) {
    return res.status(401).json({error: 'Invalid credentials'});
  }
  
  req.session.regenerate((err) => {
    if (err) return res.status(500).json({error: 'Session error'});
    req.session.userId = user.id;
    res.json({message: 'Login successful'});
  });
});

Implement proper middleware ordering and authentication guards:

const authenticate = (req, res, next) => {
  if (!req.session.userId) {
    return res.status(401).json({error: 'Authentication required'});
  }
  next();
};

// Protect all routes under /api/private
app.use('/api/private', authenticate);

// Or protect individual routes
app.get('/api/profile', authenticate, (req, res) => {
  res.json({user: req.session.userId});
});

For JWT-based authentication, use express-jwt with proper validation:

const jwt = require('express-jwt');

app.use(jwt({
  secret: process.env.JWT_SECRET,
  algorithms: ['HS256'],
  issuer: 'your-app',
  audience: 'your-audience'
}).unless({
  path: ['/login', '/public']
}));

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

How can I test if my Express authentication is vulnerable to session fixation?
Create a test session before login, then attempt to use that same session ID after authentication. If the session persists without regeneration, you're vulnerable. Use middleBrick's automated scanning to detect this pattern without manual testing.
What's the most common Express authentication mistake that leads to broken authentication?
Improper middleware ordering—placing authentication checks after route handlers. This allows unauthenticated access to protected endpoints. Always structure your Express app with authentication middleware before any protected routes.