HIGH session fixationfeathersjshmac signatures

Session Fixation in Feathersjs with Hmac Signatures

Session Fixation in Feathersjs with Hmac Signatures — how this specific combination creates or exposes the vulnerability

Session fixation occurs when an application assigns a user a session identifier before authentication and does not rotate or validate it after login. In FeathersJS applications that use Hmac Signatures for stateless authentication (typically via JWT or similar mechanisms), fixation risk shifts from traditional session cookies to the claims and key material used to generate and verify signatures.

FeathersJS itself is framework-agnostic about transport and storage, so developers often pair it with transports like Socket.io or REST hooks. When Hmac Signatures are used, the client may initially make unauthenticated requests that include a predictable or static identifier (e.g., a client-generated key ID or an unverified payload field). If the server uses this pre-authentication identifier as part of the Hmac payload without strict validation, an attacker can fixate a known value and later reuse it after the victim authenticates.

Consider an endpoint that accepts a clientToken in headers or query parameters before authentication. If the server includes this clientToken in the data signed by the Hmac key—without first verifying that the token is tied to an authenticated context—an attacker can set clientToken=attackerChosen. After the victim logs in, the server signs the same attacker-chosen token, allowing the attacker to replay the signed Hmac in subsequent requests. This bypasses the assumption that only the authenticated party can produce valid signatures.

Additionally, Hmac signature schemes require careful handling of nonce, timestamp, and key rotation. In FeathersJS, if nonces or timestamps are not enforced or are reused, an attacker can replay a fixed signed request. For example, a static nonce embedded in the signed string defeats the purpose of replay protection. The server must validate that each Hmac payload includes a fresh nonce or timestamp and that it has not been seen before, even before identity verification.

Another vector involves misconfigured service hooks where unauthenticated requests can influence authenticated behavior. If a FeathersJS service allows unauthenticated calls to update a resource that later participates in Hmac generation (e.g., modifying a shared secret or a user-specific salt), an attacker can manipulate the context used to create signatures. This is especially relevant when using external key stores or environment variables that may be indirectly influenced by unauthenticated inputs.

Real-world patterns mirror known vulnerabilities such as CVE-2020-15168 (in which improper nonce validation led to signature replay) and align with OWASP API Top 10:2023 Broken Object Level Authorization (BOLA) and Security Misconfiguration. The root cause is treating Hmac Signatures as a simple integrity check while neglecting identity binding and replay safeguards.

Hmac Signatures-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on ensuring that Hmac payloads are bound to authenticated identity, that nonces and timestamps are validated, and that pre-authentication inputs never influence signature generation.

Example 1: Binding Hmac to authenticated context

Only sign data after successful authentication, and include a user-specific stable identifier (e.g., user ID) in the signed payload. Do not include client-controlled values that exist before login.

const crypto = require('crypto');

function generateHmac(userId, timestamp, nonce, secret) {
  const payload = JSON.stringify({
    sub: userId,
    iat: timestamp,
    nonce: nonce
  });
  return crypto.createHmac('sha256', secret).update(payload).digest('hex');
}

// In a FeathersJS hook after authentication
app.service('todos').hooks({
  before: {
    create(context) {
      const { user } = context.params;
      const timestamp = Math.floor(Date.now() / 1000);
      const nonce = require('crypto').randomBytes(16).toString('hex');
      const signature = generateHmac(user._id, timestamp, nonce, process.env.HMAC_SECRET);
      context.params.headers = {
        ...context.params.headers,
        'x-auth-timestamp': timestamp,
        'x-auth-nonce': nonce,
        'x-auth-signature': signature
      };
      return context;
    }
  }
});

Example 2: Server-side validation with replay protection

The server must verify timestamp, nonce uniqueness, and signature integrity before processing the request. Use a short window for timestamps and a cache for nonces to prevent reuse.

const crypto = require('crypto');
const nonceCache = new Set(); // In production, use a distributed TTL cache

function verifyHmac(req, secret) {
  const timestamp = parseInt(req.headers['x-auth-timestamp'], 10);
  const nonce = req.headers['x-auth-nonce'];
  const receivedSignature = req.headers['x-auth-signature'];

  if (!timestamp || !nonce || !receivedSignature) {
    throw new Error('Missing authentication headers');
  }

  const now = Math.floor(Date.now() / 1000);
  const window = 5; // seconds
  if (Math.abs(now - timestamp) > window) {
    throw new Error('Timestamp outside acceptable window');
  }

  if (nonceCache.has(nonce)) {
    throw new Error('Nonce already used');
  }
  nonceCache.add(nonce);
  // In production, prune cache periodically

  const payload = JSON.stringify({
    sub: req.userId, // resolved after auth
    iat: timestamp,
    nonce: nonce
  });
  const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(receivedSignature))) {
    throw new Error('Invalid signature');
  }
  return true;
}

// In a FeathersJS hook before
app.service('todos').hooks({
  before: {
    all: [function contextVerifier(context) {
      if (context.params.headers && context.params.headers['x-auth-signature']) {
        verifyHmac(context.params, process.env.HMAC_SECRET);
        // Ensure userId is set from verified identity, not from untrusted input
        context.params.userId = context.params.user._id;
      }
      return context;
    }]
  }
});

Example 3: Avoiding pre-authentication influence on Hmac

Ensure that any data used in Hmac generation is set only after identity is established. Reject or ignore client-provided identifiers that could be fixed before login.

app.service('auth').hooks({
  before: {
    create(context) {
      // Do not use context.data.clientToken in any signing logic
      // Instead, after successful auth, generate fresh Hmac-bound values
      return context;
    }
  },
  after: {
    create(context) {
      const userId = context.result.userId;
      const timestamp = Math.floor(Date.now() / 1000);
      const nonce = require('crypto').randomBytes(16).toString('hex');
      const signature = generateHmac(userId, timestamp, nonce, process.env.HMAC_SECRET);
      return {
        ...context.result,
        meta: {
          timestamp,
          nonce,
          signature
        }
      };
    }
  }
});

These practices align with OWASP ASVS and the API Security Verification Standard, ensuring that Hmac Signatures provide integrity and authenticity without enabling fixation. For teams using managed solutions, the middleBrick CLI can scan for missing nonce validation and improper binding in Hmac flows, while the GitHub Action can enforce security gates in CI/CD pipelines.

Frequently Asked Questions

How does middleBrick detect Hmac-related session fixation issues?
middleBrick runs 12 security checks in parallel, including BOLA/IDOR and Input Validation, and maps findings to frameworks like OWASP API Top 10. It analyzes OpenAPI/Swagger specs with full \$ref resolution and correlates spec definitions with runtime behavior to highlight missing nonce enforcement and improper signature binding.
Can the middleBrick CLI integrate Hmac validation checks into CI/CD?
Yes, with the Pro plan the GitHub Action can add API security checks to your CI/CD pipeline and fail builds if risk scores exceed your threshold. It can flag Hmac-specific misconfigurations such as missing timestamp windows or nonces, helping you enforce secure signature practices before deployment.