Broken Authentication in Restify with Mutual Tls
Broken Authentication in Restify with Mutual Tls — how this specific combination creates or exposes the vulnerability
Broken Authentication in a Restify service that also uses Mutual TLS (mTLS) can occur when the application incorrectly interprets the presence of a client certificate as sufficient authentication, while failing to enforce additional identity checks at the application layer. mTLS ensures that both client and server present valid certificates during the TLS handshake, providing transport‑level identity and encryption. However, authentication — proving that the identity represented by the certificate maps to an authorized user or service — must be implemented by the application, not assumed from the TLS layer alone.
In Restify, a common misconfiguration is to rely on the presence of req.client.authorized or the existence of req.connection.getPeerCertificate() without verifying certificate attributes such as the Common Name (CN), Organizational Unit (OU), or SANs, or without mapping the certificate to a user record in a directory or database. If the server skips role‑based access control (RBAC) or fails to validate scopes/claims encoded in the certificate, an attacker who possesses a valid client certificate can authenticate successfully but may exceed their intended permissions. This is a Broken Authentication issue because the identity asserted by mTLS is not properly verified and enforced.
Additionally, Restify servers that configure TLS options without explicitly requiring client certificates (requestCert: true and rejectUnauthorized: true) may allow unauthenticated TLS handshakes to proceed. In such setups, an attacker could terminate mTLS at a proxy or load balancer and forward traffic without a client certificate; if Restify does not validate the upstream identity, authentication is effectively bypassed. OWASP API Security Top 10 category Broken Object Level Authorization (BOLA) often intersects with Broken Authentication here: a compromised or stolen client certificate enables horizontal or vertical privilege escalation when authorization checks are missing or inconsistent.
Real-world attack patterns include certificate theft and reuse, insufficient certificate revocation checking (CRL/OCSP), and accepting self‑signed or expired certificates without proper validation. For example, an API endpoint like /api/v1/users/{id} that relies solely on mTLS to identify the requester may allow an attacker with a valid certificate to iterate over user IDs if the handler does not confirm that the authenticated subject matches the requested resource. This demonstrates that mTLS provides transport identity, but application‑level authentication and authorization are still required to prevent Broken Authentication.
middleBrick’s LLM/AI Security checks are not applicable to this category, and the scanner’s 12 parallel checks include Authentication, which tests whether the endpoint properly validates credentials beyond TLS. Findings include missing user identity mapping, missing RBAC enforcement, and missing certificate validation steps, each with severity ratings and remediation guidance mapped to frameworks such as OWASP API Top 10 and PCI‑DSS.
Mutual Tls-Specific Remediation in Restify — concrete code fixes
To remediate Broken Authentication when using mTLS in Restify, enforce strict certificate validation and explicitly map authenticated identities to application permissions. Below are concrete, working examples that demonstrate correct server and client configuration, plus authorization checks that tie certificate attributes to access control.
1. Configure the Restify server to require and verify client certificates
Ensure the server requires client certificates and rejects unauthorized peers. Use a trusted CA to sign client certificates, and validate certificate fields that represent the user or service identity.
const tls = require('tls');
const fs = require('fs');
const restify = require('restify');
const options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
ca: [fs.readFileSync('ca-cert.pem')],
requestCert: true,
rejectUnauthorized: true
};
const server = restify.createServer({
tlsOptions: options,
// Disable automatic TLS handling that may bypass client cert checks
insecure: false
});
server.use((req, res, next) => {
const cert = req.connection.getPeerCertificate();
if (!cert || Object.keys(cert).length === 0) {
return res.send(401, { error: 'Unauthorized: No client certificate provided' });
}
// Validate certificate fields
const subject = cert.subject;
const commonName = subject.CN;
const orgUnit = subject.OU;
if (!commonName) {
return res.send(403, { error: 'Forbidden: Missing CN in certificate' });
}
// Map CN or OU to an internal user/service identity and attach to request
req.user = { id: commonName, orgUnit };
return next();
});
server.get('/api/v1/profile', (req, res, next) => {
// Ensure the authenticated identity matches the requested profile
const requestedId = req.params.id;
if (req.user.id !== requestedId) {
return res.send(403, { error: 'Forbidden: Identity mismatch' });
}
// Proceed with authorized response
res.send(200, { profile: `Profile for ${req.user.id}` });
return next();
});
server.listen(8080, () => {
console.log('Secure Restify server running on port 8080');
});
2. Client example with mTLS using agent options
Clients must present a valid certificate signed by the same CA trusted by the server.
const tls = require('tls');
const fs = require('fs');
const https = require('https');
const agent = new tls.Agent({
key: fs.readFileSync('client-key.pem'),
cert: fs.readFileSync('client-cert.pem'),
ca: [fs.readFileSync('ca-cert.pem')],
rejectUnauthorized: true
});
const options = {
hostname: 'api.example.com',
port: 8080,
path: '/api/v1/profile/cli-user',
method: 'GET',
agent: agent
};
const req = https.request(options, (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => console.log('Response:', data));
});
req.on('error', (e) => console.error('Request error:', e));
req.end();
3. Enforce RBAC and validate scopes/claims from certificate attributes
After mapping the certificate to an identity, apply role- and scope-based checks before processing sensitive operations.
function checkScope(user, requiredScope) {
// Example: scopes could be encoded in OU or a custom extension
const userScopes = user.orgUnit ? user.orgUnit.split(',') : [];
return userScopes.includes(requiredScope);
}
server.post('/api/v1/admin', (req, res, next) => {
if (!checkScope(req.user, 'admin')) {
return res.send(403, { error: 'Forbidden: Insufficient scope' });
}
res.send(200, { message: 'Admin action executed' });
return next();
});
These fixes ensure that mTLS is used correctly for transport identity while application‑level authentication and authorization enforce identity mapping and access control. middleBrick’s CLI tool (middlebrick scan <url>) can validate these controls by testing unauthenticated and authenticated attack surfaces, and the GitHub Action can integrate continuous checks to prevent regressions in CI/CD pipelines.
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 |
Frequently Asked Questions
Does mTLS alone prevent Broken Authentication in Restify?
How can I test my Restify endpoints for authentication issues using middleBrick?
middlebrick scan <your-api-url>. The scanner checks Authentication, BOLA/IDOR, and related controls, returning a security risk score and prioritized findings with remediation guidance.