HIGH broken authenticationhapi

Broken Authentication in Hapi

How Broken Authentication Manifests in Hapi

Broken authentication in Hapi applications typically emerges from misconfigured authentication strategies, improper session handling, and flawed token validation. Hapi's plugin-based architecture, while powerful, creates multiple attack surfaces where authentication can be bypassed or weakened.

The most common vulnerability occurs when developers register authentication strategies but fail to apply them consistently across routes. A typical pattern shows authentication configured at the server level but selectively disabled on sensitive endpoints:

const server = Hapi.server({ port: 3000 });

server.auth.strategy('jwt', 'jwt', {
  key: process.env.JWT_SECRET,
  validate: validateJWT,
  verifyOptions: { algorithms: ['HS256'] }
});

server.auth.default('jwt');

// Vulnerable route - authentication bypassed
server.route({
  method: 'GET',
  path: '/admin/users',
  options: {
    auth: false // Critical security gap
  },
  handler: (request, h) => {
    return getAllUsers();
  }
});

Another frequent issue involves improper scope validation. Hapi's scope system checks for permissions, but developers often implement weak validation logic:

const handler = (request, h) => {
  const user = request.auth.credentials;
  
  // Flawed scope check - allows privilege escalation
  if (user.scope.includes('admin')) {
    return getAllUserData();
  }
  
  return getUserData(user.id);
};

This code fails to verify that the authenticated user actually owns the data they're requesting. An attacker with 'admin' scope could access any user's data regardless of ownership.

Session fixation attacks target Hapi's cookie-based authentication when developers don't regenerate session identifiers after privilege changes:

const loginHandler = async (request, h) => {
  const { username, password } = request.payload;
  const user = await authenticateUser(username, password);
  
  // Vulnerable - session ID not regenerated
  request.cookieAuth.set(user);
  return h.redirect('/dashboard');
};

Timing attacks exploit Hapi's authentication validation functions when they use non-constant time comparisons:

const validateJWT = async (artifacts, request) => {
  const isValid = artifacts.payload.sub === 'expected-user';
  
  // Vulnerable to timing attacks
  if (isValid) {
    return { isValid: true };
  }
  return { isValid: false };
};

Credential stuffing becomes effective when Hapi applications lack rate limiting on authentication endpoints:

server.route({
  method: 'POST',
  path: '/login',
  options: {
    auth: false
  },
  handler: async (request, h) => {
    // No rate limiting - vulnerable to credential stuffing
    const { username, password } = request.payload;
    const user = await findUser(username);
    
    if (user && await verifyPassword(password, user.hash)) {
      return { success: true };
    }
    return { success: false };
  }
});

Hapi-Specific Detection

Detecting broken authentication in Hapi requires examining both configuration files and runtime behavior. The middleBrick API security scanner provides comprehensive coverage of Hapi-specific authentication vulnerabilities through its black-box scanning approach.

middleBrick's authentication module tests for several Hapi-specific patterns:

  • Authentication strategy bypass attempts on routes with auth: false or missing authentication
  • Scope validation weaknesses by testing privilege escalation paths
  • Cookie manipulation to detect session fixation vulnerabilities
  • Timing attack surface analysis on authentication validation functions
  • Rate limiting absence on authentication endpoints

The scanner actively probes endpoints with various authentication bypass techniques:

// Example of what middleBrick tests for:
const testAuthenticationBypass = async (url) => {
  // Test with missing/invalid tokens
  const responses = await Promise.all([
    fetch(url, { headers: { authorization: 'Bearer invalid' } }),
    fetch(url, { headers: { authorization: '' } }),
    fetch(url)
  ]);
  
  return responses.some(r => r.status === 200); // Should not return 200 without auth
};

middleBrick also analyzes OpenAPI specifications for Hapi applications, identifying routes that lack proper authentication annotations:

paths:
  /admin/users:
    get:
      summary: Get all users
      # Missing security requirement - vulnerability indicator
      # security: []
      responses:
        '200':
          description: User list

The CLI tool provides Hapi-specific scanning capabilities:

npm install -g middlebrick
middlebrick scan https://api.example.com --framework hapi --output json

GitHub Actions integration allows continuous monitoring of Hapi authentication security:

name: API Security Scan
on: [push, pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Run middleBrick Scan
      run: |
        npx middlebrick scan ${{ secrets.API_URL }} \
          --framework hapi \
          --threshold B \
          --output sarif > results.sarif
    - name: Upload SARIF file
      uses: github/codeql-action/upload-sarif@v1
      with:
        sarif_file: results.sarif

Hapi-Specific Remediation

Fixing broken authentication in Hapi requires implementing defense-in-depth strategies using Hapi's native authentication ecosystem. Start with proper strategy configuration and consistent application across all routes.

Implement comprehensive authentication strategy with proper validation:

const validateJWT = async (artifacts, request) => {
  const decoded = artifacts.decoded;
  const user = await findUserById(decoded.sub);
  
  if (!user || !user.active) {
    return { isValid: false };
  }
  
  // Constant time comparison to prevent timing attacks
  const isValid = crypto.timingSafeEqual(
    Buffer.from(decoded.iat.toString()),
    Buffer.from((Date.now() / 1000).toString())
  );
  
  return { isValid: isValid, credentials: user };
};

Apply authentication consistently with proper scope validation:

server.route({
  method: 'GET',
  path: '/admin/users',
  options: {
    auth: {
      strategy: 'jwt',
      scope: ['admin']
    },
    handler: (request, h) => {
      // Verify resource ownership
      if (!request.auth.credentials.isAdmin) {
        return h.response('Forbidden').code(403);
      }
      return getAllUsers();
    }
  }
});

Implement session regeneration after privilege changes:

const loginHandler = async (request, h) => {
  const { username, password } = request.payload;
  const user = await authenticateUser(username, password);
  
  // Regenerate session to prevent fixation
  request.cookieAuth.revoke();
  request.cookieAuth.set(user);
  
  return h.redirect('/dashboard');
};

Add rate limiting to authentication endpoints using Hapi's rate limiting plugins:

const ratelimit = require('hapi-rate-limitor');

await server.register({
  plugin: ratelimit,
  options: {
    user: {
      strategy: 'user',
      expire: 60,
      count: 5,
      key: request => request.auth.credentials.id
    }
  }
});

server.route({
  method: 'POST',
  path: '/login',
  options: {
    pre: [{ method: 'user' }], // Rate limiting
    auth: false,
    handler: async (request, h) => {
      // Authentication logic
    }
  }
});

Implement proper error handling to prevent information leakage:

const loginHandler = async (request, h) => {
  try {
    const { username, password } = request.payload;
    const user = await findUser(username);
    
    if (!user) {
      // Generic error to prevent username enumeration
      throw new Error('Invalid credentials');
    }
    
    const isValid = await verifyPassword(password, user.passwordHash);
    if (!isValid) {
      throw new Error('Invalid credentials');
    }
    
    return { success: true };
  } catch (err) {
    return h.response({ error: 'Authentication failed' }).code(401);
  }
};

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 my Hapi application's authentication security?
Use middleBrick's free scanning service to test your API endpoints. The scanner automatically detects authentication bypass vulnerabilities, missing authentication on sensitive routes, and weak token validation. Simply provide your API URL and receive a security score with specific findings within 15 seconds.
What's the difference between Hapi's authentication strategies and scopes?
Authentication strategies verify who a user is (JWT, Basic, OAuth), while scopes define what they're allowed to do. A common vulnerability occurs when developers apply authentication but forget to validate scopes, allowing authenticated users to access resources they shouldn't have permission for. Always implement both authentication AND authorization checks.