HIGH api rate abusefeathersjsbasic auth

Api Rate Abuse in Feathersjs with Basic Auth

Api Rate Abuse in Feathersjs with Basic Auth — how this combination creates or exposes the vulnerability

Rate abuse in a Feathersjs service with Basic Authentication can occur when authentication is validated per request but rate limiting is applied globally or not enforced at the authentication boundary. In Feathers, authentication typically hooks validate credentials and attach a user object to the connection or request context. If a rate limiter is configured only on service methods and does not account for authenticated identities, an attacker who discovers or guesses valid Basic Auth credentials can make many authenticated requests within a short window, exhausting rate limits intended for unauthenticated usage.

Consider a scenario where Basic Auth is checked in an authentication hook, and the rate limiter is applied via a global hook or service middleware. Because the rate limiter may key counts by IP only, an attacker using different credential pairs can rotate credentials within the Basic Auth realm and bypass IP-based thresholds. Even when rate limiting is applied globally, misconfiguration can allow authenticated sessions to exceed intended request volumes, enabling credential stuffing, brute-force attempts against weak passwords, or data scraping via the API.

Feathers hooks run in sequence: authentication hooks can set context.user, and subsequent service hooks can enforce authorization. If authentication does not signal a failed attempt to the rate limiter, abusive patterns are harder to detect. For example, a service might expose a /users endpoint that returns profile data. Without coupling authentication state to rate limiting, an attacker authenticating successfully with stolen credentials can iterate over user IDs (BOLA/IDOR) while staying under per-IP rate thresholds.

Another subtlety involves connection transports. Feathers can use WebSockets or REST transports; rate limiters that track REST requests may not apply to WebSocket messages, allowing authenticated subscribers to issue repeated queries or mutations unchecked. Similarly, if Basic Auth credentials are passed on each request, but tokens or sessions are also used, the rate limiter might not correlate across mechanisms, creating inconsistent enforcement.

Real-world attack patterns mirror OWASP API Top 10 #3:2023 — Injection and excessive data exposure — where authenticated abuse leads to enumeration or data leakage. A scanner testing unauthenticated endpoints may flag missing global rate limiting, but authenticated paths require additional checks. The combination of per-request Basic Auth validation and inconsistent rate limiting amplifies risk: valid credentials enable sustained abuse, while weak passwords make brute force feasible.

To detect this during a scan, middleware instrumentation and runtime observation are required. middleBrick runs 12 security checks in parallel, including Rate Limiting and Authentication, and can surface whether authenticated paths are subject to the same controls as unauthenticated ones. Its findings include severity ratings and remediation guidance mapped to compliance frameworks such as OWASP API Top 10 and SOC2, helping teams identify gaps where authentication and rate limiting do not align.

Basic Auth-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on aligning authentication with rate limiting and ensuring that each authenticated identity is accounted for. Below are concrete Feathers hooks and configuration examples to reduce risk.

1. Apply rate limiting after authentication and include user identity in the key

Use a rate limiter that factors in the authenticated user ID when available, falling back to IP when not. This prevents credential rotation attacks and ensures per-user quotas.

// src/hooks/rate-limit.js
const { RateLimiterMemory } = require('rate-limiter-flexible');

const rateLimiter = new RateLimiterMemory({
  points: 100, // 100 requests
  duration: 60 // per 60 seconds
});

function rateLimitAuthenticated(context) {
  return rateLimiter.consume(context.params.user ? context.params.user._id : context.params.ip)
    .then(() => {})
    .catch(() => {
      throw new Error('Too Many Requests');
    });
}

module.exports = { rateLimitAuthenticated };

2. Configure Feathers authentication to reject malformed or repeated Basic credentials

Ensure the authentication hook validates credentials strictly and does not silently accept weak or reused passwords. Combine with a custom hook to track failed attempts per user.

// src/authentication.js
const { AuthenticationService, JWTStrategy, LocalStrategy } = require('@feathersjs/authentication');
const { iff, isProvider } = require('@feathersjs/hooks-common');
const { authenticate } = require('@feathersjs/authentication').hooks;
const { rateLimitFailedAttempts } = require('./hooks/rate-limit-failed');

module.exports = {
  service: 'authentication',
  config: {
    secret: process.env.SECRET,
    strategies: ['local']
  },
  hooks: {
    before: {
      all: [iff(isProvider('external'), authenticate('session')), rateLimitFailedAttempts],
      local: [authenticate('local')]
    }
  }
};

3. Enforce consistent rate limits across transports

Apply the same rate limiting logic to REST and WebSocket channels. Use a shared store (e.g., Redis) to correlate requests and messages across transports.

// src/hooks/transport-rate-limit.js
const { RateLimiterRedis } = require('rate-limiter-flexible');
const { REDIS_URL } = process.env;

const redisRateLimiter = new RateLimiterRedis({
  storeClient: require('redis').createClient({ url: REDIS_URL }),
  points: 30,
  duration: 60
});

function transportRateLimit(context) {
  return redisRateLimiter.consume(context.params.user ? context.params.user._id : context.params.ip)
    .then(() => {})
    .catch(() => {
      throw new Error('Rate limit exceeded on transport');
    });
}

module.exports = { transportRateLimit };

4. Validate and normalize Basic Auth credentials in hooks

Use a before hook to parse and validate the Authorization header, rejecting malformed inputs early and normalizing realm handling to avoid bypass via casing or whitespace.

// src/hooks/validate-basic-auth.js
function validateBasicAuth(context) {
  const auth = context.params.headers && context.params.headers.authorization || '';
  const match = auth.match(/^Basic\s+(\S+)$/i);
  if (!match) {
    throw new Error('Unauthorized');
  }
  const decoded = Buffer.from(match[1], 'base64').toString('utf8');
  const [username, password] = decoded.split(':').map(s => s.trim());
  if (!username || !password) {
    throw new Error('Invalid credentials');
  }
  context.params.basic = { username, password };
  return context;
}

module.exports = { validateBasicAuth };

5. Combine authentication hooks with service-level guards

Even after authentication, apply per-method or per-entity checks to ensure users only access their own resources, reducing the impact of compromised credentials.

// src/users/hooks.js
const { iff, isProvider } = require('@feathersjs/hooks-common');

function ensureOwnership(context) {
  if (context.params.user && context.id !== context.params.user._id) {
    throw new Error('Forbidden');
  }
  return context;
}

module.exports = {
  before: {
    all: [iff(isProvider('rest'), ensureOwnership)]
  }
};

These hooks should be added alongside existing service configurations. They ensure that authenticated requests are uniquely tracked for rate limiting, credentials are validated consistently across transports, and ownership checks reduce lateral movement risks. middleBrick’s checks for Rate Limiting and Authentication can highlight misconfigurations where these practices are absent.

Frequently Asked Questions

How does middleBrick detect rate abuse when Basic Auth is used?
middleBrick runs parallel checks including Authentication and Rate Limiting. It examines whether rate controls consider authenticated identities and whether credentials can be rotated to bypass IP-based thresholds, surfacing findings with severity and remediation.
Can middleBrick scan Feathersjs services with Basic Auth?
Yes. middleBrick submits a URL for unauthenticated black-box scanning; it does not require credentials. It checks whether rate limiting is applied consistently and maps findings to frameworks like OWASP API Top 10.