# Rate-Limiting Strategy in DeskcommCRM: Fixed-Window Protection with Redis

> Discover DeskcommCRM's fixed-window rate-limiting strategy using Redis to protect authentication endpoints. Learn about IP and identifier limits against brute-force attacks.

- Repository: [Rafael Melgaço/DeskcommCRM](https://github.com/melgarafael/DeskcommCRM)
- Tags: internals
- Published: 2026-09-12

---

**DeskcommCRM employs a fixed-window rate-limiting strategy using Redis counters to protect authentication endpoints, applying separate IP-based and identifier-based limits to prevent brute-force attacks.**

DeskcommCRM implements a robust rate-limiting strategy to safeguard its authentication surface against abuse and distributed attacks. The system relies on Redis-backed counters managed through Upstash, with core logic residing in [`lib/auth/rate-limit.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/auth/rate-limit.ts). This approach utilizes a fixed-window algorithm with dual-dimensional throttling to balance security and user experience.

## How the Fixed-Window Rate Limiter Works

The implementation leverages a **fixed-window** algorithm rather than a sliding window, providing burst-tolerant protection that resets after configurable time intervals. Each authentication attempt increments a counter in Redis using atomic `INCR` and `EXPIRE` operations, ensuring accurate tracking even under concurrent load.

### Two-Dimensional Bucket Strategy

The rate-limiting strategy applies **two-dimensional limits** that operate independently:

- **Per-IP buckets** isolate traffic from single sources, preventing individual networks from overwhelming the system.
- **Per-identifier buckets** throttle attempts against specific accounts (emails or tokens), protecting against distributed brute-force attacks that rotate IP addresses.

This dual approach ensures that an attacker cannot bypass limits simply by switching networks or targeting multiple accounts from a single location.

### Privacy-Preserving Key Hashing

All IP addresses and identifiers are hashed using **sha256** before storage in Redis. This key construction method keeps bucket keys opaque, preventing the leakage of raw client data while maintaining consistent rate-limit tracking. The hashing occurs in [`lib/auth/rate-limit.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/auth/rate-limit.ts) before any Redis operations.

### Graceful Fallback for Missing IPs

When client IP addresses cannot be determined (`null`), the system skips IP-based limits rather than applying a global bucket. This **fallback handling** prevents a single misconfigured proxy from triggering a denial-of-service lockout for the entire installation. Requests without IPs remain subject to identifier-based limits, maintaining partial protection.

### Environment-Based Configuration

Default limits are exported in the `AUTH_LIMITS` constant (lines [136-146] of [`lib/auth/rate-limit.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/auth/rate-limit.ts)). Administrators can override these values through environment variables such as `AUTH_RATE_LIMIT_LOGIN_IP`. Invalid configurations automatically fall back to production defaults, ensuring the system remains protected even with misconfiguration.

## Actions Covered by Rate Limiting

The `authRateLimited` function (lines [64-100]) enforces specific limits for five distinct authentication actions defined in the `AUTH_LIMITS` object.

### Login Protection

The **login** action applies the strictest controls: **60 attempts per 5 minutes per IP** and **5 attempts per 5 minutes per account**. This dual limit blocks both single-source brute-force attacks and distributed attempts against high-value accounts. Failed attempts trigger `registrarFalhaDeLogin` to increment the per-identifier counter.

### Signup Throttling

Account creation is limited to **20 attempts per hour per IP** through the **signup** action. This prevents mass account registration while allowing legitimate team growth. Unlike login, signup typically applies only IP-based limits since the account identifier does not yet exist.

### Password Reset Security

The **reset** action restricts password recovery to **30 attempts per hour per IP** and **3 attempts per hour per account**. These tight limits prevent automated enumeration and mass-reset attacks while providing legitimate users sufficient retry capacity.

### Invitation and Organization Recovery

Two specialized flows receive dedicated protection:

- **invite_accept**: Limited to **60 attempts per hour per IP**, throttling acceptance of invitation tokens without restricting legitimate team onboarding.
- **org_recovery**: Highly restricted to **5 attempts per hour per IP** and **3 attempts per hour per account**, protecting the first-access recovery flow that creates new organizations.

## Implementation Code Examples

The rate limiter integrates into authentication flows through the `authRateLimited` helper. Below is the pattern used to protect login endpoints in DeskcommCRM:

```typescript
import { authRateLimited, AUTH_LIMITS } from "@/lib/auth/rate-limit";
import { contaBloqueadaPorFalhas, registrarFalhaDeLogin } from "@/lib/auth/rate-limit";

async function handleLogin(email: string, password: string) {
  // Check both IP and identifier buckets before processing
  if (await authRateLimited("login", email, AUTH_LIMITS.login)) {
    return { error: "Muitas tentativas – aguarde e tente novamente." };
  }

  const valid = await verifyPassword(email, password);
  if (!valid) {
    // Record failure for per-account tracking
    await registrarFalhaDeLogin(email, AUTH_LIMITS.login);
    if (await contaBloqueadaPorFalhas(email, AUTH_LIMITS.login)) {
      return { error: "Conta temporariamente bloqueada por falhas." };
    }
    return { error: "Credenciais inválidas." };
  }

  return { success: true };
}

```

For signup endpoints, the implementation passes `null` as the identifier since the account does not yet exist:

```typescript
async function handleSignup(email: string) {
  if (await authRateLimited("signup", null, AUTH_LIMITS.signup)) {
    return { error: "Muitas tentativas de cadastro – aguarde." };
  }
  // Account creation logic follows...
}

```

## Reusable Infrastructure Across the Platform

Beyond authentication, the underlying `checkRateLimit` function from [`lib/ai/dispatcher/rate-limit.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/ai/dispatcher/rate-limit.ts) serves as the generic engine for **webhook capture** and the **AI dispatcher**. This shared infrastructure ensures consistent throttling semantics across all resource-intensive operations in DeskcommCRM.

## Summary

- DeskcommCRM implements a **fixed-window rate-limiting strategy** using Redis (Upstash) with atomic `INCR` and `EXPIRE` operations.
- **Two-dimensional limits** track both per-IP and per-identifier (email/token) buckets to prevent distributed attacks.
- Keys are hashed with **sha256** before storage to protect client privacy.
- The system covers five authentication actions—**login**, **signup**, **reset**, **invite_accept**, and **org_recovery**—with specific thresholds for each.
- Missing IP addresses trigger **fallback handling** that skips IP limits rather than applying global restrictions.
- Configuration occurs through the `AUTH_LIMITS` constant with environment variable overrides.

## Frequently Asked Questions

### What type of rate-limiting algorithm does DeskcommCRM use?

DeskcommCRM uses a **fixed-window rate-limiting** algorithm implemented in [`lib/auth/rate-limit.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/auth/rate-limit.ts). This approach increments a single counter for each time window rather than tracking sliding time boundaries, providing burst-tolerant protection that expires after a configurable number of seconds (`windowSec`).

### How does DeskcommCRM prevent rate-limit keys from leaking sensitive data?

The system hashes all IP addresses and identifiers using **sha256** before constructing Redis keys. This ensures that raw client data never appears in the keyspace, maintaining privacy while allowing consistent rate tracking across the fixed windows defined in `AUTH_LIMITS`.

### Can administrators customize the rate limits without modifying code?

Yes. While default values are hardcoded in the `AUTH_LIMITS` constant (lines [136-146]), administrators can override specific limits through environment variables such as `AUTH_RATE_LIMIT_LOGIN_IP`. Invalid values automatically fall back to production defaults to prevent accidental unprotected states.

### What happens if the system cannot determine the client's IP address?

When IP detection returns `null`, the rate limiter applies **fallback handling** by skipping the IP-based bucket entirely. The request remains subject to identifier-based limits (if applicable), preventing a global DoS condition that would lock out all users due to a single misconfigured proxy or network condition.