Skip to Content

Limitación de Tasa

Auris aplica límites de tasa en todos los endpoints de la API para proteger la plataforma contra abusos, prevenir ataques de credential stuffing y garantizar una asignación justa de recursos entre tenants. Esta guía explica los niveles de limitación de tasa, cómo leer las cabeceras de límite, cómo gestionar respuestas 429 Too Many Requests en tu aplicación y cómo configurar los límites.

Niveles de Limitación de Tasa

Auris aplica diferentes límites de tasa según la sensibilidad y el coste de recursos de cada endpoint. Existen cuatro niveles:

Nivel Auth (Estricto)

Se aplica a los endpoints de autenticación que manejan credenciales:

  • POST /api/auth/login (inicio de sesión con correo/contraseña)

  • POST /api/auth/signup (registro de usuario)

  • POST /api/auth/token (intercambio y refresco de tokens)

  • POST /api/auth/magic-link (inicio del magic link)

  • POST /api/auth/passwordless/* (flujos sin contraseña)

  • POST /api/oauth/authenticate (envío del formulario de inicio de sesión alojado)

Estos endpoints tienen los límites más estrictos porque son el objetivo principal de los ataques de credential stuffing y fuerza bruta.

Límites por defecto: Pocas solicitudes por minuto por IP, con límites adicionales por cuenta en los endpoints de inicio de sesión.

Nivel Sensible (Moderado)

Se aplica a operaciones críticas de seguridad que no deberían llamarse con frecuencia:

  • POST /api/user/2fa/* (registro y verificación de 2FA)

  • POST /api/auth/forgot-password (inicio del restablecimiento de contraseña)

  • POST /api/auth/change-password (cambio de contraseña)

  • POST /api/user/phone/* (verificación de número de teléfono)

Límites por defecto: Solicitudes moderadas por minuto por IP y por usuario.

Nivel API (Estándar)

Se aplica a los endpoints de API autenticados generales:

  • GET/POST/PATCH/DELETE /api/users/*

  • GET/POST/PATCH/DELETE /api/roles/*

  • GET/POST/PATCH/DELETE /api/organizations/*

  • GET/POST/PATCH/DELETE /api/applications/*

  • Todos los demás endpoints CRUD autenticados

Límites por defecto: Solicitudes estándar por minuto por usuario autenticado.

Nivel Público (Relajado)

Se aplica a los endpoints abiertos que no requieren autenticación:

  • GET /.well-known/openid-configuration (OIDC Discovery)

  • GET /.well-known/jwks.json (JWKS)

  • GET /api/public/* (páginas de estado públicas, páginas de verificación)

  • POST /api/scim/v2/* (aprovisionamiento SCIM con token bearer)

Límites por defecto: Límites generosos, solo basados en IP.

Leer las Cabeceras de Límite de Tasa

Cada respuesta de un endpoint con limitación de tasa incluye cabeceras estándar que indican el estado actual de tu ventana de límite:

| Cabecera | Tipo | Descripción |

|----------|------|-------------|

| X-RateLimit-Limit | Entero | Número máximo de solicitudes permitidas en la ventana actual |

| X-RateLimit-Remaining | Entero | Número de solicitudes restantes antes de alcanzar el límite |

| X-RateLimit-Reset | Timestamp Unix | Cuándo se reinicia la ventana actual (segundos desde epoch) |

| Retry-After | Entero | Segundos hasta que puedas reintentar (solo presente en respuestas 429) |

Ejemplo de cabeceras de respuesta en una solicitud exitosa:

HTTP/1.1 200 OK X-RateLimit-Limit: 100 X-RateLimit-Remaining: 87 X-RateLimit-Reset: 1737014400 Content-Type: application/json

Ejemplo de cabeceras de respuesta cuando se alcanza el límite de tasa:

HTTP/1.1 429 Too Many Requests X-RateLimit-Limit: 100 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1737014400 Retry-After: 47 Content-Type: application/json { "ok": false, "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Demasiadas solicitudes. Por favor, inténtalo de nuevo en 47 segundos." } }

Manejar Respuestas 429

Cuando tu aplicación recibe una respuesta 429 Too Many Requests, debe retroceder y reintentar después del tiempo indicado en la cabecera Retry-After.

Reintento Básico con Retroceso

async function callAurisApi( url: string, options: RequestInit, maxRetries = 3 ): Promise<Response> { for (let attempt = 0; attempt <= maxRetries; attempt++) { const response = await fetch(url, options) if (response.status !== 429) { return response } // Leer la cabecera Retry-After const retryAfter = parseInt(response.headers.get('Retry-After') || '60', 10) if (attempt === maxRetries) { throw new Error( `Límite de tasa alcanzado tras ${maxRetries} reintentos. Reintenta en ${retryAfter}s.` ) } console.warn( `Límite de tasa alcanzado (intento ${attempt + 1}/${maxRetries}). ` + `Reintentando en ${retryAfter} segundos...` ) // Esperar la duración especificada await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000)) } throw new Error('Inesperado: se superó el bucle de reintentos') } // Uso const response = await callAurisApi( 'https://auth.tuempresa.com/api/users', { headers: { Authorization: `Bearer ${accessToken}`, 'x-tenant': 'your-tenant-id', }, } )

Retroceso Exponencial con Jitter

Para sistemas en producción que manejan tráfico elevado, usa retroceso exponencial con jitter para evitar el problema de thundering herd cuando muchos clientes alcanzan los límites simultáneamente:

async function callWithExponentialBackoff( url: string, options: RequestInit, maxRetries = 5 ): Promise<Response> { for (let attempt = 0; attempt <= maxRetries; attempt++) { const response = await fetch(url, options) if (response.status !== 429) { return response } if (attempt === maxRetries) { throw new Error('Límite de tasa superado: máximo de reintentos alcanzado') } // Usar Retry-After si está disponible, sino retroceso exponencial const retryAfter = response.headers.get('Retry-After') let delay: number if (retryAfter) { delay = parseInt(retryAfter, 10) * 1000 } else { // Retroceso exponencial: 1s, 2s, 4s, 8s, 16s const baseDelay = Math.pow(2, attempt) * 1000 // Añadir jitter aleatorio (0-50% del retraso base) const jitter = Math.random() * baseDelay * 0.5 delay = baseDelay + jitter } await new Promise((resolve) => setTimeout(resolve, delay)) } throw new Error('Inesperado: se superó el bucle de reintentos') }

Patrón Circuit Breaker

Para aplicaciones que realizan muchas llamadas a la API, implementa un circuit breaker para dejar de enviar solicitudes completamente cuando los límites se alcanzan de forma consistente:

class AurisCircuitBreaker { private failureCount = 0 private lastFailure = 0 private state: 'closed' | 'open' | 'half-open' = 'closed' private readonly threshold = 5 private readonly resetTimeout = 60000 // 1 minuto async call(fn: () => Promise<Response>): Promise<Response> { if (this.state === 'open') { if (Date.now() - this.lastFailure > this.resetTimeout) { this.state = 'half-open' } else { throw new Error('El circuit breaker está abierto. Las solicitudes están pausadas.') } } const response = await fn() if (response.status === 429) { this.failureCount++ this.lastFailure = Date.now() if (this.failureCount >= this.threshold) { this.state = 'open' console.error( `Circuit breaker abierto tras ${this.threshold} límites de tasa alcanzados. ` + `Pausando solicitudes durante ${this.resetTimeout / 1000}s.` ) } throw new Error('Límite de tasa alcanzado') } // Éxito — reiniciar el circuit breaker this.failureCount = 0 this.state = 'closed' return response } }

Límites por Cuenta en Endpoints de Autenticación

Además de los límites basados en IP, los endpoints de autenticación aplican límites por cuenta que funcionan junto con el sistema de protección contra fuerza bruta:

| Umbral | Acción |

|--------|--------|

| Inicios de sesión fallidos consecutivos dentro de la ventana de observación | Contador incrementado |

| El contador alcanza el umbral de bloqueo (por defecto: 5) | Cuenta bloqueada por una duración creciente |

| 1er bloqueo | 5 minutos |

| 2do bloqueo | 30 minutos |

| 3er bloqueo | 24 horas |

Estos límites son por cuenta de usuario y persisten entre direcciones IP. Un ataque distribuido desde múltiples IPs contra la misma cuenta también activará el bloqueo.

El bloqueo por cuenta es independiente de la limitación de tasa basada en IP. Una IP puede estar limitada mientras la cuenta objetivo permanece desbloqueada (si el contador de fallos no ha alcanzado el umbral), y viceversa.

Consulta la guía de Protección Contra Ataques para los detalles completos sobre la configuración de protección contra fuerza bruta.

Comportamiento de Reintento Automático del SDK

El SDK @auris/js incluye manejo integrado de límites de tasa para operaciones con tokens:

  • Refresco de token: Si una solicitud de refresco de token recibe un 429, el SDK espera la duración de Retry-After y reintenta una vez automáticamente

  • Redirección al inicio de sesión: El flujo de inicio de sesión alojado se renderiza en el servidor y no está sujeto a límites de tasa del lado del cliente

  • Llamadas a la API mediante el cliente de Gestión: El cliente de Gestión no reintenta automáticamente — tu aplicación debe implementar la lógica de reintentos

import { AurisClient } from '@auris/js' const auris = new AurisClient({ domain: 'auth.tuempresa.com', clientId: 'your-client-id', autoRefresh: true, // El SDK gestiona el refresco con reintento integrado }) // El reintento del refresco de token es automático // Si el endpoint de refresco devuelve 429, el SDK espera y reintenta const token = await auris.getAccessToken()

Para el cliente de Gestión (M2M), implementa tu propia lógica de reintentos:

import { AurisClient } from '@auris/js' const management = new AurisClient.Management({ domain: 'auth.tuempresa.com', clientId: 'm2m-client-id', clientSecret: 'm2m-client-secret', }) // Las llamadas al cliente de Gestión deben usar tu propio wrapper de reintentos const users = await callWithExponentialBackoff( 'https://auth.tuempresa.com/api/users', { headers: { Authorization: `Bearer ${await management.getToken()}`, 'x-tenant': 'your-tenant-id', }, } )

Configuración desde la Consola

La configuración de limitación de tasa es visible en la Consola de Auris en Configuración → Limitación de Tasa. La Consola muestra la configuración actual para cada nivel en modo de solo lectura.

Los ajustes mostrados incluyen:

  • Límites por nivel — Solicitudes por ventana para cada nivel (auth, sensible, api, público)

  • Duración de la ventana — El tamaño de la ventana deslizante para cada nivel

  • Estado actual — Si la limitación de tasa está activa

Los valores de límite de tasa se configuran a nivel de infraestructura y se muestran en la Consola como referencia. Para solicitar cambios en los umbrales de limitación de tasa para tu tenant, contacta a tu administrador de Auris o ajusta la configuración del entorno.

Monitorización Proactiva de Límites de Tasa

En lugar de esperar respuestas 429, monitoriza la cabecera X-RateLimit-Remaining de forma proactiva para reducir tu tasa de solicitudes antes de alcanzar los límites:

class RateLimitAwareClient { private remaining = Infinity private resetAt = 0 async request(url: string, options: RequestInit): Promise<Response> { // Si sabemos que estamos en el límite, esperar proactivamente if (this.remaining <= 1 && Date.now() / 1000 < this.resetAt) { const waitMs = (this.resetAt - Date.now() / 1000) * 1000 console.log(`Esperando proactivamente ${waitMs}ms para evitar el límite de tasa`) await new Promise((resolve) => setTimeout(resolve, waitMs)) } const response = await fetch(url, options) // Actualizar el estado del límite de tasa desde las cabeceras de respuesta const limit = response.headers.get('X-RateLimit-Remaining') const reset = response.headers.get('X-RateLimit-Reset') if (limit !== null) this.remaining = parseInt(limit, 10) if (reset !== null) this.resetAt = parseInt(reset, 10) return response } }

Buenas Prácticas

Respeta siempre Retry-After. Cuando recibes un 429, la cabecera Retry-After te indica exactamente cuánto tiempo esperar. No reintentes antes de que transcurra ese período.

Usa retroceso exponencial con jitter. Para operaciones en bloque o escenarios de alto rendimiento, el reintento lineal simple puede causar picos de tráfico cuando múltiples clientes reintenten al mismo momento. El jitter distribuye los reintentos en el tiempo.

Implementa circuit breakers para rutas críticas. Si tu aplicación depende de llamadas a la API de Auris en la ruta de solicitudes (p. ej., comprobaciones de permisos), usa un circuit breaker para fallar de forma controlada en lugar de encolar solicitudes mientras estás limitado.

Almacena en caché las respuestas siempre que sea posible. Reduce las llamadas a la API almacenando en caché perfiles de usuario, listas de roles y comprobaciones de permisos. El SDK @auris/react usa TanStack Query con un staleTime predeterminado que reduce las llamadas a la API redundantes.

Usa operaciones en bloque cuando estén disponibles. Utiliza endpoints de operaciones masivas (p. ej., operaciones en bloque de SCIM, escrituras de tuplas FGA en bloque) en lugar de llamadas individuales a la API para realizar el mismo trabajo con menos solicitudes.

Monitoriza las cabeceras de límite de tasa en producción. Registra el valor de X-RateLimit-Remaining y configura alertas cuando caiga por debajo de un umbral. Esto te da una advertencia temprana antes de que los usuarios empiecen a ver errores 429.

Guías Relacionadas