Broken Authentication in Feathersjs with Basic Auth
Broken Authentication in Feathersjs with Basic Auth — how this specific combination creates or exposes the vulnerability
FeathersJS is a framework for real-time applications that can expose HTTP and WebSocket transports. When Basic Authentication is used naively, the framework’s flexibility can allow unauthenticated or weakly authenticated access to service routes. Basic Auth transmits credentials in an easily decoded Base64 string, and if the transport does not enforce authentication on every request, attackers can replay or manipulate credentials.
In a FeathersJS service, authentication is typically implemented via hooks. If a developer configures the authentication flag but does not apply the hook to all relevant methods—or configures it only for specific transports—methods left unguarded permit direct access. For example, a GET endpoint that lists sensitive resources without validating credentials becomes an information disclosure vector. An attacker can enumerate user data or service metadata by simply omitting the Authorization header, because FeathersJS may still consider the request valid if the hook is not applied globally.
Another common pattern is embedding credentials in URLs (e.g., http://user:pass@host/service). Browsers and HTTP clients may send these credentials automatically, but FeathersJS may not validate them correctly if the transport layer does not enforce strict header-based checks. This can lead to authentication bypass when clients rely on URL credentials while the server expects Authorization headers. Additionally, if the service does not enforce HTTPS, Basic Auth credentials are exposed in transit, enabling credential theft via network sniffing.
Consider a FeathersJS service defined without transport-specific authentication rules. An unauthenticated attacker can probe the API endpoint with a missing or malformed Authorization header. Because the service lacks validation, the request succeeds, revealing data that should be restricted. This aligns with the BOLA/IDOR class of issues when the exposed data includes other users’ resources, and it can be discovered during an unauthenticated scan run by middleBrick, which tests the attack surface without credentials.
Real-world findings from such scans have referenced patterns seen in CVE-2020-15267, where improper validation allowed unauthorized access to API endpoints. The OWASP API Security Top 10 categorizes this as Broken Authentication, specifically under ‘Improper Enforcement of Authentication.’ The risk is elevated when combined with other checks such as missing rate limiting or excessive data exposure, as middleBrick’s 12 parallel checks can identify in a 5–15 second scan.
Basic Auth-Specific Remediation in Feathersjs — concrete code fixes
Remediation focuses on enforcing authentication on every service method and avoiding transport leakage. Use FeathersJS hooks to validate the Authorization header on each request, and ensure the hook applies to all transports (HTTP and WebSocket). Never rely on URL credentials alone.
The following example demonstrates a secure FeathersJS authentication hook for Basic Auth. It decodes the header, validates credentials against a user service, and attaches the user object to the request context. The hook is registered globally so it runs for every method and transport.
const { AuthenticationError } = require('@feathersjs/errors');
function basicAuthHook(options = {}) {
return async context => {
const { headers } = context.params;
const authHeader = headers && headers.authorization;
if (!authHeader || !authHeader.startsWith('Basic ')) {
throw new AuthenticationError('Missing or invalid Authorization header');
}
const base64 = authHeader.split(' ')[1];
const decoded = Buffer.from(base64, 'base64').toString('utf-8');
const [username, password] = decoded.split(':');
if (!username || !password) {
throw new AuthenticationError('Invalid credentials format');
}
// Replace with your actual user lookup and password verification
const userService = context.app.service('users');
const user = await userService.find({ query: { username } });
if (!user.total || user.data.length === 0) {
throw new AuthenticationError('Invalid credentials');
}
const valid = await verifyPassword(password, user.data[0].passwordHash);
if (!valid) {
throw new AuthenticationError('Invalid credentials');
}
context.params.user = user.data[0];
return context;
};
}
function verifyPassword(input, hash) {
// Use a constant-time comparison in production, e.g., bcrypt.compare
return input === hash;
}
// Apply globally to all services
app.hooks({
before: {
all: [basicAuthHook()],
services: []
},
after: {
all: [],
services: []
},
error: {
all: [],
services: []
}
});
Additionally, enforce HTTPS in production to protect credentials in transit. Configure your server to redirect HTTP to HTTPS and set the Strict-Transport-Security header. Avoid logging Authorization headers, and ensure that responses do not inadvertently expose user data, which could amplify BOLA/IDOR risks.
For continuous assurance, use the middleBrick CLI to scan from the terminal with middlebrick scan <url>, or integrate the GitHub Action to fail builds if security scores drop. The dashboard allows you to track scores over time, and the Pro plan supports continuous monitoring with configurable alerts. These features help detect regressions in authentication handling before they reach production.
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 |