HIGH brute force attackfeathersjsapi keys

Brute Force Attack in Feathersjs with Api Keys

Brute Force Attack in Feathersjs with Api Keys — how this specific combination creates or exposes the vulnerability

A brute force attack against an API that uses static API keys in a FeathersJS service can occur when the key is treated as a low-entropy secret or when the service does not enforce strict request-rate controls. FeathersJS itself is framework-agnostic about authentication; if you implement API key validation in a hook or a custom service without additional protections, an attacker who knows or guesses a valid key can repeatedly attempt to authenticate and iterate over resources.

Consider a FeathersJS service that uses an API key passed via an Authorization header (e.g., Bearer <key>). If the endpoint does not enforce per-key rate limiting and returns distinct responses for valid versus invalid keys, it may leak key validity. A brute force or online guessing attack then becomes feasible: the attacker submits many candidate keys and observes HTTP 200 versus 401/403 responses to narrow valid keys. This is an online attack because the service provides feedback that enables iterative guessing.

Another scenario involves weak key generation. If keys are short, predictable, or derived from low-entropy sources (e.g., timestamps without sufficient randomness), an attacker can generate candidates and validate them against the FeathersJS service. Even if the keys are stored securely server-side, the API surface may expose endpoints that do not enforce account lockout, captcha, or exponential backoff. Without these protections, the API key becomes a static credential that, if leaked or discovered, allows unchecked access until manually rotated.

Additionally, if your FeathersJS application exposes an OpenAPI spec that inadvertently documents the API key in examples or debug output, automated scanners or attackers may discover valid keys. When combined with a lack of rate limiting, this can lead to successful brute force attempts. The framework does not inherently prevent these issues; they depend on how you configure authentication, validation, and monitoring in your services and hooks.

Api Keys-Specific Remediation in Feathersjs — concrete code fixes

To mitigate brute force risks when using API keys in FeathersJS, apply rate limiting, key rotation, and strict validation. Use a dedicated rate-limiting strategy tied to the key itself, and ensure invalid keys do not reveal information via timing differences or distinct error messages.

Example 1: Basic API key validation hook with constant-time comparison and rate limiting using an in-memory store (replace with Redis or a distributed store in production):

// src/hooks/validate-api-key.js
const rateLimitStore = new Map(); // key -> { count, lastSeen }

module.exports = function apiKeyHook(options = {}) {
  return async context => {
    const authHeader = context.headers.authorization || '';
    const key = authHeader.startsWith('Bearer ') ? authHeader.slice(7) : '';
    const now = Date.now();
    const windowMs = options.windowMs || 60_000; // 1 minute
    const maxRequests = options.maxRequests || 60;

    if (!key) {
      throw new Error('Not authenticated');
    }

    // Constant-time check to avoid timing leaks
    const isValid = await context.app.service('keys').find({
      query: { _id: key, active: true },
      paginate: false
    }).then(res => res.data.length === 1).catch(() => false);

    // Rate limiting per key
    const record = rateLimitStore.get(key) || { count: 0, lastSeen: now };
    if (now - record.lastSeen > windowMs) {
      record.count = 0;
      record.lastSeen = now;
    }
    record.count += 1;
    rateLimitStore.set(key, record);

    if (record.count > maxRequests) {
      throw new Error('Rate limit exceeded');
    }

    if (!isValid) {
      throw new Error('Invalid API key');
    }

    // Attach key metadata to context for downstream services
    context.params.apiKey = key;
    return context;
  };
};

Register the hook in your service configuration:

// src/services/items/index.js
const validateApiKey = require('./hooks/validate-api-key');

module.exports = function (app) {
  const options = {
    name: 'items',
    before: {
      all: [validateApiKey({ windowMs: 60_000, maxRequests: 60 })],
      find: [],
      get: [],
      create: [],
      update: [],
      patch: [],
      remove: []
    }
  };
  app.use('/items', options);
  const service = app.service('items');
  service.hooks(options.before);
};

Example 2: Rotate keys via a separate key service and enforce short-lived keys where feasible. Store keys with a hashed representation and include metadata such as creation time and scope:

// src/services/keys/index.js
const crypto = require('crypto');

module.exports = function (app) {
  app.service('keys').hooks({
    before: {
      create: [context => {
        // Generate a high-entropy key
        const raw = crypto.randomBytes(32).toString('hex');
        context.data.key = raw;
        context.data.hashedKey = crypto.createHash('sha256').update(raw).digest('hex');
        context.data.createdAt = new Date().toISOString();
        context.data.active = true;
        return context;
      }],
      authenticate: [context => {
        const { hashedKey } = context.data;
        // Compare hashes in constant time
        const candidate = crypto.createHash('sha256').update(context.data.keyCandidate).digest('hex');
        const match = crypto.timingSafeEqual(Buffer.from(hashedKey), Buffer.from(candidate));
        if (!match) {
          throw new Error('Invalid key');
        }
        return context;
      }]
    }
  });
};

Additional recommendations: integrate a distributed rate limiter (e.g., Redis-based sliding window), avoid returning whether a key is valid in timing-sensitive paths, rotate keys on suspicion, and monitor request patterns per key. These steps reduce the feasibility of brute force attacks against your FeathersJS API key authentication.

Frequently Asked Questions

Can middleware-based API key validation in FeathersJS prevent brute force attacks on its own?
Middleware validation helps, but it must be combined with rate limiting and constant-time checks. Without per-key rate limits and timing-safe validation, an attacker can still probe valid keys.
How does middleBrick handle API key brute force risks in scans?