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: truetells the TLS layer to request a client certificate.rejectUnauthorized: trueensures that connections with invalid or untrusted certificates are rejected.capoints 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.tlsand 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 ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |