Security Misconfiguration in Feathersjs with Jwt Tokens
Security Misconfiguration in Feathersjs with Jwt Tokens
FeathersJS is a framework for real-time APIs. When JWT tokens are used for authentication, several specific misconfigurations can expose endpoints or allow unauthorized access. These misconfigurations intersect with the framework’s service hooks, JWT strategy setup, and runtime behavior, creating scenarios where authentication bypass or privilege escalation becomes possible.
One common pattern is defining a custom authentication strategy without enforcing strict origin checks or token validation on every service. For example, initializing the JWT strategy with minimal constraints and attaching it to a service can allow unauthenticated requests to reach the service if hooks are not explicitly configured. An attacker could call the service endpoint directly, relying on missing route-level authentication enforcement.
Another vulnerability arises from improper hook ordering. FeathersJS allows hooks to run in sequence, but if the authentication hook is placed after a hook that modifies or trusts request parameters, an attacker might manipulate IDs or query filters to access other users’ data (BOLA/IDOR). This becomes critical in services like /messages where an ID is passed in the URL. Without verifying ownership in an earlier hook, the system may leak data across users.
Additionally, failing to validate token claims such as roles or scopes can lead to privilege escalation. If a JWT contains a role claim but the server does not re-check it against an authorization policy on each request, a user with a low-privilege token could perform admin actions. Misconfigured CORS settings combined with JWT in cookies or headers can also expose tokens to cross-origin requests, increasing the risk of token leakage or replay.
In some cases, services inadvertently expose JWT-related endpoints or configuration in the OpenAPI spec. If the spec includes routes like /login without requiring authentication for documentation or introspection endpoints, an attacker can enumerate valid login paths or probe for weak password policies. This aligns with the broader Security Misconfiguration category, where exposed endpoints, verbose error messages, and missing access controls amplify risk.
Using middleBrick’s OpenAPI/Swagger spec analysis, these issues can be cross-referenced with runtime findings. The scanner tests unauthenticated attack surfaces across the 12 checks, including Authentication, Authorization, and Input Validation, to highlight gaps in how JWT is enforced across FeathersJS services.
Jwt Tokens-Specific Remediation in Feathersjs
Remediation focuses on tightening JWT validation, hook ordering, and claim checks within FeathersJS services. Below are concrete code examples that demonstrate secure configurations.
Secure JWT Strategy Initialization
Configure the JWT strategy with strict origin and claim validation. This example uses the @feathersjs/authentication-jwt package and ensures that roles are validated on each request:
// src/authentication.js
const { AuthenticationService, JWTStrategy } = require('@feathersjs/authentication');
const { express } = require('@feathersjs/express');
const app = express();
app.configure(authentication({
secret: process.env.JWT_SECRET,
entity: 'user',
service: 'users',
jwt: {
header: { typ: 'JWT' },
audience: 'https://api.yourdomain.com',
issuer: 'feathersjs-auth',
algorithms: ['HS256']
}
}));
app.use('/authentication', new AuthenticationService({
name: 'authentication',
paginate: { default: 10, max: 50 },
}));
// Ensure the JWT strategy is used and roles are checked
app.service('authentication').hooks({
before: {
create: [authentication.hooks.authenticate(['jwt'])]
}
});
Service-Level Hook Enforcement
Apply authentication hooks to each service and validate roles before allowing access. This prevents unauthenticated calls and enforces role-based checks:
// src/services/messages/messages.hooks.js
const { iff, isProvider } = require('feathers-hooks-common');
const { GeneralError } = require('@feathersjs/errors');
const ensureAuthenticated = (context) => {
if (!context.params.user) {
throw new GeneralError('Authentication required', { code: 401 });
}
return context;
};
const ensureAdmin = (context) => {
const { user } = context.params;
if (!user || user.role !== 'admin') {
throw new GeneralError('Forbidden: insufficient permissions', { code: 403 });
}
return context;
};
module.exports = {
before: {
all: [
iff(isProvider('external'), ensureAuthenticated),
iff(isProvider('external'), ensureAdmin) // Apply only where needed
],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
}
};
Ownership Validation to Prevent IDOR
For services accepting an id parameter, validate that the resource belongs to the requesting user. This mitigates BOLA/IDOR issues:
// src/services/messages/messages.hooks.js
const { iff, isProvider, preventChanges } = require('feathers-hooks-common');
const filterToUser = async (context) => {
const { user, id } = context.params;
if (user && id) {
const record = await context.app.service('messages').get(id);
if (record.userId !== user.id) {
throw new GeneralError('Access denied', { code: 403 });
}
}
return context;
};
module.exports = {
before: {
get: [iff(isProvider('external'), filterToUser)],
// similar for patch/remove
}
};
These configurations, combined with CORS restrictions and careful OpenAPI spec generation, reduce the likelihood of misconfiguration. middleBrick’s scans can highlight whether authentication hooks are consistently applied and whether JWT claims are properly validated across endpoints.