HIGH identification failuresadonisjsmutual tls

Identification Failures in Adonisjs with Mutual Tls

Identification Failures in Adonisjs with Mutual Tls

Identification failures occur when an API fails to establish a trusted identity for a peer before processing a request. In Adonisjs combined with Mutual TLS (mTLS), this typically means the server does not properly validate the client certificate, or the client does not validate the server certificate. mTLS relies on two-way authentication: both sides present and verify digital certificates. When this process is misconfigured in Adonisjs, the framework may accept unauthenticated or spoofed connections, leading to authorization bypasses or data exposure.

Adonisjs does not enforce mTLS by default; you integrate it via the underlying Node.js HTTPS server. A common misconfiguration is providing an HTTPS server with only a server-side certificate and key, omitting the requestCert and rejectUnauthorized options. Without these, the server does not request or validate client certificates, breaking the mTLS handshake and allowing any client to connect. Another pitfall is failing to verify the certificate chain against a trusted Certificate Authority (CA), which permits connections with self-signed or malicious certificates.

An mTLS-enabled Adonisjs server in JavaScript typically looks like this, correctly requesting and verifying client certificates:

const fs = require('fs')
const https = require('https')
const { Ignitor } = require('@adonisjs/ignitor')

new Ignitor(require('@adonisjs/fold'))
  .fireHttpServer()
  .then(() => {
    const server = https.createServer({
      key: fs.readFileSync('server-key.pem'),
      cert: fs.readFileSync('server-cert.pem'),
      ca: fs.readFileSync('ca-cert.pem'),
      requestCert: true,
      rejectUnauthorized: true
    }, (req, res) => {
      // If the client provided a valid certificate, req.socket.getPeerCertificate() is populated
      const cert = req.socket.getPeerCertificate()
      if (!cert || Object.keys(cert).length === 0) {
        res.writeHead(401)
        res.end('Client certificate required')
        return
      }
      // Optionally inspect certificate fields for identification
      const subject = cert.subject
      res.writeHead(200, { 'Content-Type': 'application/json' })
      res.end(JSON.stringify({ message: 'Authenticated', subject }))
    })
    server.listen(8443, () => console.log('mTLS server running on https://localhost:8443'))
  })
  .catch((error) => {
    console.error('Server failed to start', error)
  })

If you omit requestCert and rejectUnauthorized, or set rejectUnauthorized to false, the server accepts connections without valid client certificates. Similarly, if the client does not present a certificate signed by the CA trusted by the server, the handshake fails or, when improperly handled, incorrectly succeeds. This leads to identification failures where the server cannot distinguish legitimate clients from unauthorized ones.

Another scenario involves the client not validating the server certificate. A client built with Adonisjs (e.g., using native https or a library like axios with an HTTPS agent) must provide a CA bundle and set rejectUnauthorized to ensure it is communicating with the intended server. Skipping this exposes the client to man-in-the-middle attacks even when mTLS is used for server authentication.

These identification failures map to the BOLA/IDOR and Authentication checks in middleBrick’s 12 security scans. middleBrick will flag missing client certificate validation as a high-severity finding and will note unverified server certificates under encryption and data exposure checks. Because middleBrick tests the unauthenticated attack surface, it can detect whether an endpoint accepts connections without proper mTLS, providing prioritized findings with remediation guidance.

Remediation centers on strict certificate validation on both sides, using code patterns that enforce verification and inspecting certificate details. Always set requestCert and rejectUnauthorized on the server, and provide a CA bundle on the client while ensuring the server’s certificate matches the expected hostname.

Mutual Tls-Specific Remediation in Adonisjs

To remediate identification failures in Adonisjs with mTLS, enforce certificate validation on both server and client, verify certificate metadata, and handle errors explicitly. Below are concrete code examples demonstrating secure mTLS setups.

Secure mTLS server in Adonisjs:

const fs = require('fs')
const https = require('https')
const { Ignitor } = require('@adonisjs/ignitor')

new Ignitor(require('@adonisjs/fold'))
  .fireHttpServer()
  .then(() => {
    const server = https.createServer({
      key: fs.readFileSync('server-key.pem'),
      cert: fs.readFileSync('server-cert.pem'),
      ca: fs.readFileSync('ca-cert.pem'),
      requestCert: true,
      rejectUnauthorized: true
    }, (req, res) => {
      const cert = req.socket.getPeerCertificate()
      if (!cert || Object.keys(cert).length === 0) {
        res.writeHead(401)
        res.end('Client certificate required')
        return
      }
      // Verify certificate fields (example: check common name or extended key usage)
      const subject = cert.subject
      const fingerprint = cert.fingerprint
      // Implement additional checks as needed, e.g., against an allowlist
      res.writeHead(200, { 'Content-Type': 'application/json' })
      res.end(JSON.stringify({ message: 'Authenticated', subject, fingerprint }))
    })
    server.listen(8443, () => console.log('mTLS server running on https://localhost:8443'))
  })
  .catch((error) => {
    console.error('Server failed to start', error)
  })

Secure mTLS client in Node.js (usable within Adonisjs services or scripts):

const fs = require('fs')
const https = require('https')

const agent = new https.Agent({
  key: fs.readFileSync('client-key.pem'),
  cert: fs.readFileSync('client-cert.pem'),
  ca: fs.readFileSync('ca-cert.pem'),
  rejectUnauthorized: true
})

https.get('https://localhost:8443', { agent }, (res) => {
  console.log('statusCode:', res.statusCode)
  res.on('data', (d) => {
    process.stdout.write(d)
  })
}).on('error', (error) => {
  console.error('Client error', error)
})

Additional guidance:

  • Always set requestCert: true and rejectUnauthorized: true on the server to require and validate client certificates.
  • Use a dedicated CA certificate (via ca) to verify peer certificates, avoiding insecure fallbacks.
  • On the client, provide the client certificate, key, and the same CA bundle, with rejectUnauthorized: true to ensure server certificate validation.
  • Inspect certificate fields such as subject and fingerprint to implement allowlisting or additional business-rule checks.
  • Handle handshake and verification errors explicitly to avoid failing open.

These practices reduce the risk of identification failures and align with the checks performed by middleBrick’s scans, which include unauthenticated endpoint detection and encryption verification.

Frequently Asked Questions

What does an identification failure look like in an mTLS-enabled Adonisjs API scan?
middleBrick will flag missing client certificate validation or missing server certificate verification as high-severity findings, noting that the endpoint accepts connections without proper mTLS and may expose authentication weaknesses.
Can middleBrick verify mTLS configurations?
Yes. middleBrick scans the unauthenticated attack surface and can detect whether an endpoint requires and validates client certificates, and it reports on encryption settings and certificate verification issues with remediation guidance.