HIGH broken authenticationhapimutual tls

Broken Authentication in Hapi with Mutual Tls

Broken Authentication in Hapi with Mutual Tls — how this specific combination creates or exposes the vulnerability

Hapi is a rich framework for building web applications and services in Node.js. When Mutual TLS (mTLS) is used for authentication, the client presents a certificate that the server must validate. Broken authentication can occur in this setup if the server does not enforce strict certificate validation, does not map the certificate to a user identity, or does not apply proper authorization after authentication.

mTLS provides transport-layer authentication, but it does not automatically equate to application-level authorization. A common vulnerability pattern with Hapi and mTLS is accepting any presented certificate without verifying the certificate chain, hostname, or revocation status. For example, if you configure an Hapi server to request client certificates but do not set a proper CA to validate them, an attacker could present a self-signed certificate and be treated as a trusted client.

Another issue is missing or weak mapping between the certificate subject (e.g., CN or SAN) and application users or roles. Hapi can access the client certificate via request.plugins.tls or the socket object, but if you do not explicitly extract and validate the identity from the certificate, you might rely on implicit trust. Additionally, failing to enforce authorization checks after authentication means that a low-privilege certificate could perform privileged operations, leading to Broken Function Level Authorization (BFLA) or Insecure Direct Object References (IDOR).

During a middleBrick scan, such misconfigurations appear as authentication findings when the unauthenticated or mTLS-authenticated attack surface reveals endpoints that either improperly accept unauthenticated requests or do not validate mTLS certificates correctly. These findings highlight gaps between transport-layer identity and application-layer access control, which is especially critical when handling sensitive data or compliance requirements like PCI-DSS or HIPAA.

Mutual Tls-Specific Remediation in Hapi — concrete code fixes

Remediation centers on strict server-side validation of client certificates and explicit mapping of certificate attributes to application identities and permissions.

1. Configure an Hapi server with proper mTLS options

Use the TLS settings to require and validate client certificates against a trusted CA. Below is a concrete, working example of an Hapi server configured for mTLS:

const Hapi = require('@hapi/hapi');
const fs = require('fs');

const init = async () => {
  const server = Hapi.server({
    port: 443,
    host: '0.0.0.0',
    tls: {
      key: fs.readFileSync('/path/to/server-key.pem'),
      cert: fs.readFileSync('/path/to/server-cert.pem'),
      ca: fs.readFileSync('/path/to/ca-bundle.pem'),
      requestCert: true,
      rejectUnauthorized: true
    }
  });

  server.route({
    method: 'GET',
    path: '/secure',
    handler: (request, h) => {
      const tls = request.plugins.tls;
      if (!tls || !tls.client) {
        return h.response({ error: 'Unauthorized' }).code(401);
      }
      const subject = tls.client.subject;
      const serialNumber = tls.client.serialNumber;
      // Map certificate fields to your user/role logic here
      return h.response({ message: 'Authenticated', subject, serialNumber });
    },
    options: {
      auth: false // mTLS handled via tls.requestCert; implement custom auth strategy if needed
    }
  });

  await server.start();
  console.log('Server running on %s', server.info.uri);
};

init().catch(err => {
  console.error(err);
  process.exit(1);
});

Key points in this example:

  • requestCert: true tells the TLS layer to request a client certificate.
  • rejectUnauthorized: true ensures that connections with invalid or untrusted certificates are rejected.
  • ca points to a CA bundle used to verify the client certificate chain.
  • The handler explicitly checks for the presence of a client certificate via request.plugins.tls and extracts identity fields (subject, serialNumber) for mapping to application users.

If you use an auth strategy, you can integrate mTLS validation into it. For example, a custom auth scheme can inspect the TLS socket and reject requests where the certificate is missing or attributes do not match an allowed list.

2. Map certificate identity and enforce authorization

After authenticating via mTLS, you must map the certificate to an application identity and enforce authorization. Avoid implicit trust; always validate the certificate fields against an allowlist or directory service. Here is an example of mapping and authorization within a route handler:

const allowedSubjects = new Set(['CN=alice,O=Example', 'CN=bob,O=Example']);

server.route({
  method: 'POST',
  path: '/resource/{id}',
  handler: (request, h) => {
    const tls = request.plugins.tls;
    if (!tls || !tls.client) {
      throw Boom.unauthorized('Client certificate required');
    }
    const subject = tls.client.subject;
    if (!allowedSubjects.has(subject)) {
      throw Boom.forbidden('Certificate not allowed');
    }
    // Additional authorization: check if the certificate subject is permitted to modify this resource
    const resourceId = request.params.id;
    if (!canAccessResource(subject, resourceId)) {
      throw Boom.forbidden('Insufficient permissions for this resource');
    }
    return h.response({ updated: resourceId });
  }
});

function canAccessResource(subject, resourceId) {
  // Implement your mapping and policy logic here
  return true;
}

These steps reduce the risk of Broken Authentication by ensuring that mTLS is properly enforced, certificates are validated, identities are explicitly mapped, and authorization checks are applied consistently.

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 does mTLS alone not prevent Broken Authentication in Hapi?
mTLS provides transport-layer authentication but does not enforce application-level authorization. If the server does not validate the certificate chain, map certificate attributes to users, and apply authorization checks, an attacker with a valid certificate can still perform unauthorized actions.
What should I include in my CA bundle for Hapi mTLS?
Include all intermediate and root CAs that issued the client certificates you trust. The CA bundle must be referenced via the `ca` option in the Hapi TLS configuration so that `rejectUnauthorized: true` can verify the full chain.