Broken Authentication in Hapi with Jwt Tokens
Broken Authentication in Hapi with Jwt Tokens — how this specific combination creates or exposes the vulnerability
Hapi is a rich framework for building HTTP services, and when it is used to handle JWT-based authentication, several specific implementation choices can lead to Broken Authentication. A JWT is typically validated on each request; if Hapi routes are not strict about audience, issuer, and algorithm, an attacker can supply a token issued for another audience or signed with a different algorithm and have it accepted.
In a black-box scan, middleBrick tests unauthenticated endpoints and then exercises authentication flows using malformed or manipulated JWTs. For example, if an Hapi server decodes the JWT header to determine the algorithm before verifying the signature, an attacker can provide {"alg":"none"} in the header and a valid-looking token, causing the server to accept an unsigned token as authenticated. Similarly, weak secret handling or predictable secrets makes token forgiting feasible, and missing token revocation checks enable reused or compromised tokens to remain valid.
Another common pattern is missing or permissive CORS in Hapi, which can allow a browser-based attacker to make authenticated requests on behalf of a victim. middleBrick checks for these server-side behaviors by submitting tokens with invalid issuers, missing claims, and mismatched audiences, then inspecting whether routes reject them. Findings are mapped to OWASP API Top 10 (2023) API1:2023 (Broken Object Level Authorization often overlaps with Broken Authentication when token scope is too broad) and to patterns such as insecure default configurations, which can be enumerated in the per-category breakdown provided in the scan report.
When integrating with identity providers, ensure that JWT validation enforces strict algorithm whitelisting (e.g., HS256 or RS256), validates exp and nbf, and checks iss and aud. middleBrick’s LLM/AI Security checks include tests for system prompt leakage and prompt injection, but for API authentication it focuses on whether malformed or unsigned tokens are incorrectly accepted, which is a strong indicator of Broken Authentication in Hapi services using JWTs.
Jwt Tokens-Specific Remediation in Hapi — concrete code fixes
To remediate Broken Authentication with JWTs in Hapi, enforce strict validation on every request and avoid any dynamic algorithm selection. Below are concrete, working examples using the hapi-auth-jwt2 plugin and the jsonwebtoken library for key material management.
1) Server setup with strict JWT validation
Configure the server to require HTTPS in production, use a strong secret or asymmetric key, and explicitly set accepted algorithms.
const Hapi = require('@hapi/hapi');
const Jwt = require('@hapi/jwt');
const validate = async (decoded, request, h) => {
// Perform additional application-level checks here, e.g., token revocation list
const isValid = true; // replace with real checks
if (!isValid) {
return { isValid: false };
}
return { isValid: true, credentials: decoded };
};
const init = async () => {
const server = Hapi.server({
port: 4000,
host: 'localhost',
routes: {
cors: {
origin: ['https://your-trusted-frontend.com'],
additionalHeaders: ['authorization', 'content-type']
}
}
});
await server.register(Jwt);
server.auth.strategy('jwt', 'jwt', {
keys: process.env.JWT_SECRET || 'a-very-long-and-secure-random-secret-here',
verify: {
aud: 'https://api.yourdomain.com',
iss: 'https://auth.yourdomain.com',
algorithms: ['HS256']
},
validate: validate
});
server.auth.default('jwt');
server.route({
method: 'GET',
path: '/profile',
options: {
auth: 'jwt',
handler: (request, h) => {
// request.auth.credentials contains the validated decoded JWT payload
return { user: request.auth.credentials.userId, scope: request.auth.credentials.scope };
}
}
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
init().catch((err) => {
console.error(err);
});
2) Rotate secrets and use environment variables
Do not hardcode secrets. Use environment variables and rotate them regularly. If you use asymmetric keys, load the public key for verification and keep the private key in a secure vault.
// Example of asymmetric key usage (optional)
const fs = require('fs');
const path = require('path');
const publicKey = fs.readFileSync(path.join(__dirname, 'keys', 'public.pem'));
server.auth.strategy('jwt', 'jwt', {
keys: publicKey,
verify: {
aud: 'https://api.yourdomain.com',
iss: 'https://auth.yourdomain.com',
algorithms: ['RS256']
}
});
3) Enforce token expiration and nonce checks where applicable
Always set exp and validate nbf. For state-changing operations, consider one-time nonces or short-lived tokens. The following route demonstrates how to require specific scopes within the token.
server.route({
method: 'POST',
path: '/transfer',
options: {
auth: 'jwt',
handler: (request, h) => {
const { scope } = request.auth.credentials;
if (!scope.includes('transfer:write')) {
throw Boom.forbidden('Insufficient scope');
}
// proceed with the operation
return { status: 'ok' };
}
}
});
4) MiddleBrick checks and continuous monitoring
Use the middleBrick CLI to validate your configuration: middlebrick scan https://your-api.example.com. In the Pro plan, enable continuous monitoring so that any regression in JWT validation is flagged immediately. The GitHub Action can fail a build if the risk score drops below your chosen threshold, and the MCP Server allows you to run scans directly from your IDE while developing.
Reminder: middleBrick detects and reports these issues but does not fix, patch, or block. Review the findings and apply the guidance to harden your Hapi 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 |