Broken Authentication in Hapi with Basic Auth
Broken Authentication in Hapi with Basic Auth — how this specific combination creates or exposes the vulnerability
Hapi is a rich framework that does not enforce authentication by default. When Basic Auth is added manually—typically via a simple header check or a lightweight plugin—developers often validate credentials but omit critical protections such as TLS, rate limiting, and proper credential storage. This combination exposes authentication to several well known weaknesses mapped in the OWASP API Top 10, notably Broken Authentication (API1:2023).
Without transport layer encryption, credentials encoded with Base64 are transmitted in clear text and can be intercepted. Hapi servers that accept Authorization headers but do not enforce HTTPS allow any network observer to harvest valid credentials. Even when HTTPS is used, weak password policies or reused credentials increase the risk of credential stuffing or brute force attacks.
Another common pattern is storing secrets in environment variables or configuration files without rotation or access controls. If an attacker gains read access to the deployment environment (for example, through a misconfigured server or a log exposure), these credentials are directly usable. Hapi applications that fail to hash and salt passwords, or that store them in plaintext, amplify the impact of a data exposure finding (Data Exposure check in middleBrick).
Missing account lockout or exponential backoff enables automated credential guessing. Hapi routes that accept login requests without rate limiting allow attackers to iterate over username and password combinations quickly. Insecure consumption of authentication tokens—such as storing session identifiers in local storage without the Secure and HttpOnly flags—can lead to token theft via cross-site scripting (XSS), compounding the authentication risk.
Finally, overly permissive CORS configurations can allow unauthorized origins to invoke authentication endpoints. If Hapi responses include broad Access-Control-Allow-Origin headers, attackers may craft malicious web pages that trigger authenticated requests on behalf of users. Each of these gaps turns a seemingly simple Basic Auth setup into a vector covered by the Authentication and related checks in a middleBrick scan.
Basic Auth-Specific Remediation in Hapi — concrete code fixes
Remediation focuses on enforcing transport security, protecting credentials, and hardening the authentication flow. Always serve Hapi over TLS, store passwords using a strong adaptive hash, and apply rate limiting to authentication endpoints.
Example: Secured Hapi server with Basic Auth
// Install dependencies: npm install @hapi/hapi @hapi/basic @hapi/boom argon2
const Hapi = require('@hapi/hapi');
const BasicAuth = require('@hapi/basic');
const Boom = require('@hapi/boom');
const argon2 = require('argon2');
// In-memory store for example; use a secure database in production
const users = [
{
id: 'user-123',
username: 'api-user',
passwordHash: argon2.hash('StrongPassword123!') // store only the hash
}
];
const validate = async (request, username, password, h) => {
const user = users.find(u => u.username === username);
if (!user) {
return { credentials: null, isValid: false };
}
const isValid = await argon2.verify(user.passwordHash, password);
return { credentials: user, isValid };
};
const register = async (server) => {
await server.register(BasicAuth);
server.auth.strategy('simple', 'basic', { validate });
server.auth.default('simple');
};
const init = async () => {
const server = Hapi.server({
port: 443,
host: '0.0.0.0',
tls: {
key: fs.readFileSync('/path/to/private.key'),
cert: fs.readFileSync('/path/to/certificate.crt')
}
});
await register(server);
// Apply rate limiting at the connection or route level
server.ext('onPreResponse', (request, h) => {
// Implement token bucket or similar; omitted for brevity
return h.continue;
});
server.route({
method: 'POST',
path: '/login',
options: {
auth: false, // handled at strategy level or use custom validation
handler: (request, h) => {
// After auth, issue a short lived token instead of reusing Basic credentials
return h.response({ message: 'Authenticated' }).code(200);
}
}
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
init().catch(err => {
console.error(err);
process.exit(1);
});
Key remediation points illustrated:
- Transport security: TLS termination on port 443 with proper key and certificate files.
- Password storage: Use argon2 (or bcrypt/scrypt) to store only password hashes, never plaintext.
- Validation: The validate function checks credentials against the stored hash and returns a credentials object for downstream use.
- Authentication strategy: Register and set a default Basic Auth strategy so protected routes require valid credentials.
- Rate limiting and token issuance: Apply rate limiting at the server or route level and consider issuing short lived session tokens after successful authentication to reduce exposure of Basic credentials.
For continuous monitoring, you can run a middleBrick scan against your Hapi endpoint. The scan tests unauthenticated attack surfaces and maps findings to frameworks such as OWASP API Top 10 and provides remediation guidance without altering your service.
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 |