Broken Authentication in Feathersjs
How Broken Authentication Manifests in Feathersjs
Broken authentication in Feathersjs often stems from misconfigured authentication hooks, improper session management, or inadequate validation of user credentials. Feathersjs uses a pluggable authentication system where services can be protected with authenticate hooks, but developers frequently make critical mistakes in implementation.
One common vulnerability occurs when developers forget to apply authentication hooks to critical services. For example, an admin management service might be exposed without proper authentication:
const adminService = app.service('admin/users');
// Missing authentication hook!
// Any unauthenticated user can access this service
Another frequent issue involves improper JWT validation. Feathersjs supports multiple JWT strategies, but developers sometimes use weak secret keys or fail to validate token expiration:
// INSECURE: Hardcoded weak secret
const authService = new AuthenticationService(app, {
secret: 'password123', // Easily guessable
strategies: ['jwt']
});
Session fixation attacks are particularly problematic in Feathersjs applications that use session-based authentication. If session IDs aren't properly regenerated after login, attackers can fixate sessions and hijack accounts:
// INSECURE: Session ID not regenerated
app.post('/login', async (req, res) => {
const user = await findUser(req.body);
if (user) {
req.session.user = user; // Session fixation vulnerability
res.json({ success: true });
}
});
Feathersjs's flexible authentication system can also lead to privilege escalation when role-based access control (RBAC) isn't properly enforced. Developers might check user roles in service methods but forget to protect the entire service:
class AdminService {
async find(params) {
// INSECURE: Role check only in method
if (!params.user.roles.includes('admin')) {
throw new Forbidden('Admin access required');
}
return this._super.find(params);
}
}
// But the service itself isn't protected by an authentication hook
Credential stuffing becomes easier when Feathersjs applications don't implement proper rate limiting on authentication endpoints. Without rate limiting, attackers can brute-force passwords indefinitely:
// INSECURE: No rate limiting on login
app.post('/login', async (req, res) => {
const { email, password } = req.body;
const user = await User.authenticate('local', { email, password });
// No rate limiting, no account lockout
res.json(user);
});
Feathersjs-Specific Detection
Detecting broken authentication in Feathersjs requires both static code analysis and dynamic runtime testing. Start by examining your authentication configuration and service protection patterns.
Static analysis should focus on these key areas:
// Check for missing authentication hooks
const unprotectedServices = [
'admin/*',
'settings/*',
'users/me'
].filter(path => {
const service = app.service(path);
return !service.hooks || !service.hooks._before.some(h => h.name === 'authenticate');
});
Verify your JWT configuration for security best practices:
const jwtConfig = app.get('authentication');
const issues = [];
if (jwtConfig.secret.length < 32) {
issues.push('JWT secret too short');
}
if (jwtConfig.expiresIn && jwtConfig.expiresIn < '1h') {
issues.push('JWT expiration too short');
}
if (!jwtConfig.issuer || !jwtConfig.audience) {
issues.push('JWT issuer/audience not configured');
}
Dynamic testing with middleBrick can identify authentication bypasses that static analysis misses. middleBrick's black-box scanning tests unauthenticated access to protected endpoints:
npm install -g middlebrick
middlebrick scan https://api.yourapp.com/users/me \
--report=json > auth-report.json
# middleBrick will test:
# - Access to protected endpoints without authentication
# - JWT token validation weaknesses
# - Session management vulnerabilities
# - Rate limiting effectiveness
middleBrick's LLM/AI Security module is particularly valuable for Feathersjs applications using AI features, as it tests for system prompt leakage and prompt injection vulnerabilities that could bypass authentication logic in AI-powered services.
Manual penetration testing should include:
- Testing for default credential acceptance
- Verifying account lockout mechanisms
- Checking for session fixation vulnerabilities
- Testing privilege escalation paths
- Verifying JWT token tampering resistance
Feathersjs-Specific Remediation
Securing authentication in Feathersjs requires a defense-in-depth approach using the framework's built-in features and security best practices.
Start with proper authentication hook configuration. Apply authentication globally to protected services:
const { authenticate } = require('@feathersjs/authentication').hooks;
// Secure all admin services
app.service('admin').hooks({
before: {
all: [
authenticate('jwt'), // Require JWT for all admin operations
query.withParams(), // Prevent parameter injection
]
}
});
Implement strong JWT configuration with proper secrets and validation:
const crypto = require('crypto');
const authService = new AuthenticationService(app, {
secret: crypto.randomBytes(32).toString('base64'), // 256-bit random secret
strategies: ['jwt'],
jwt: {
header: { alg: 'HS256' },
expiresIn: '24h',
issuer: 'your-app.com',
audience: 'your-app.com'
}
});
Prevent session fixation by regenerating session IDs after authentication:
app.post('/login', async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.authenticate('local', { email, password });
// Regenerate session to prevent fixation
req.session.regenerate(err => {
if (err) return res.status(500).json({ error: 'Session error' });
req.session.user = user;
res.json({ success: true, user });
});
} catch (error) {
res.status(401).json({ error: 'Invalid credentials' });
}
});
Implement rate limiting on authentication endpoints using Feathersjs middleware:
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // Limit each IP to 5 requests per windowMs
message: 'Too many login attempts, please try again later',
standardHeaders: true,
legacyHeaders: false,
});
app.post('/login', loginLimiter, async (req, res) => {
// Authentication logic here
});
Secure role-based access control using Feathersjs's authorization hooks:
const { iff, isProvider, fastJoin } } from 'feathers-hooks-common';
const adminOnly = context => context.params.user.roles.includes('admin');
app.service('admin/users').hooks({
before: {
all: [
authenticate('jwt'),
iff(adminOnly, fastJoin(protectAdminData)) // Only admins see sensitive data
]
}
});
const protectAdminData = mergeSchema({
admin: () => false
});
Enable continuous monitoring with middleBrick's Pro plan to automatically scan your Feathersjs APIs for authentication vulnerabilities:
# Add to GitHub Actions for CI/CD security
- name: Scan API Security
uses: middlebrick/middlebrick-action@v1
with:
url: ${{ secrets.API_URL }}
fail-on-severity: high
token: ${{ secrets.MIDDLEBRICK_TOKEN }}
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 |