Tema 18
La seguridad de una API no empieza cuando se agregan filtros, tokens o middlewares. Empieza cuando se decide qué recursos se exponen, cómo evolucionan las versiones, qué operaciones pueden repetirse sin riesgo y cuánto del sistema queda realmente visible. El diseño condiciona la superficie de ataque mucho antes de la implementación detallada.
Hay APIs que resultan difíciles de asegurar no porque les falten controles, sino porque fueron diseñadas con demasiada exposición, demasiadas excepciones o demasiada flexibilidad. Cuando la arquitectura publica más recursos de los necesarios, mezcla funciones distintas o mantiene versiones viejas sin criterio, la seguridad se vuelve reactiva y costosa.
En cambio, un diseño más sobrio y deliberado reduce superficie de ataque, simplifica autorización, facilita observabilidad y vuelve más razonable el mantenimiento de políticas a lo largo del tiempo.
Este tema se centra en tres ideas que impactan mucho la seguridad desde el diseño: versionado, idempotencia y minimización de exposición.
Seguridad en diseño significa tomar decisiones estructurales que limiten riesgo antes de depender de mitigaciones posteriores. No se trata solo de “agregar seguridad temprano”, sino de modelar la API de una forma que haga más difícil cometer ciertos errores y más fácil aplicar controles coherentes.
Esto incluye preguntas como:
Una API segura expone lo necesario y no más. Cada endpoint, cada método, cada parámetro opcional y cada versión adicional amplía superficie de ataque, carga operativa y complejidad de autorización.
Minimizar exposición implica:
Las acciones especiales suelen ser más difíciles de proteger que los recursos claros. Cuando la API acumula endpoints como `recalculate`, `force-sync`, `approveNow`, `doMagicThing` o equivalentes, aparecen funciones con semántica ambigua, alto impacto y reglas difíciles de auditar.
Siempre que sea posible, conviene modelar operaciones como transformaciones controladas de recursos o estados, no como comandos ad hoc difíciles de gobernar.
El versionado permite evolucionar la API sin romper clientes, pero también crea riesgo. Cada versión mantenida es una interfaz adicional que necesita autenticación, autorización, monitoreo, parches, documentación y pruebas. Cuantas más versiones conviven, más difícil se vuelve asegurar comportamiento coherente.
Los riesgos más comunes del versionado son:
Versionar bien no es solo agregar `/v2/` o un header. También implica definir cómo se retiran versiones viejas, cuánto tiempo conviven y bajo qué condiciones se les siguen aplicando mejoras de seguridad.
Un diseño maduro debería responder:
Cada versión adicional es una forma de deuda. No solo porque suma mantenimiento, sino porque multiplica caminos que un atacante puede explorar. A veces el mayor problema no es una vulnerabilidad en la versión actual, sino una interfaz olvidada que sigue expuesta con controles de otra época.
Por eso conviene ver el inventario de versiones como parte del inventario de superficie de ataque.
Una operación idempotente es aquella cuyo efecto observable no cambia si se ejecuta varias veces con la misma intención. En APIs, este concepto es importante tanto para resiliencia como para seguridad.
Desde el punto de vista técnico, la idempotencia ayuda a manejar reintentos y fallos de red. Desde el punto de vista de seguridad, ayuda a limitar el impacto de duplicaciones accidentales, replay o automatización sobre ciertas operaciones.
Muchas acciones sensibles no deberían ejecutarse dos veces con el mismo efecto: pagos, compras, canjes, aprobaciones, cambios de estado críticos o generación de beneficios. Si el sistema no diseña bien esas operaciones, un replay o un simple retry puede provocar fraude, inconsistencias o abuso.
La idempotencia ayuda a responder preguntas como:
No toda operación puede ser naturalmente idempotente, pero muchas pueden diseñarse para resistir repetición. Algunas estrategias incluyen:
Esto es especialmente importante en operaciones económicas o de alto impacto funcional.
HTTP ya ofrece una semántica aproximada sobre operaciones idempotentes y no idempotentes, pero el diseño de la API debe respetarla de forma coherente. Si una operación de efecto fuerte se expone como `GET`, o si un `POST` crea resultados duplicables sin defensa, el protocolo deja de ayudar y la seguridad se resiente.
Diseñar con semántica clara facilita que caches, clientes, reintentos y herramientas de monitoreo se comporten de manera previsible.
Otra decisión de diseño crítica es separar claramente tipos de exposición. No todos los consumidores ni todos los recursos deberían vivir en la misma superficie visible.
Conviene distinguir:
Mezclar estos mundos en los mismos dominios, rutas o políticas suele aumentar el riesgo y la complejidad innecesariamente.
La minimización de exposición también se traduce en diseñar endpoints, respuestas y flujos de modo que cada actor vea y haga solo lo necesario. Es mucho más fácil aplicar mínimo privilegio cuando la interfaz ya fue pensada con esa restricción en mente.
Ejemplos:
La flexibilidad suele verse como virtud de diseño, pero en seguridad tiene costo. Cuantos más filtros libres, parámetros opcionales, operadores complejos, payloads dinámicos o caminos alternativos se permitan, más difícil resulta validar, autorizar y monitorear.
Una API segura prefiere contratos acotados y claros antes que interfaces excesivamente expresivas que después nadie puede controlar del todo.
En APIs reales, muchas decisiones de seguridad compiten con backward compatibility. A veces un comportamiento inseguro se mantiene para no romper clientes existentes. El problema aparece cuando esa compatibilidad se vuelve excusa para no endurecer nunca.
La seguridad en diseño exige una postura más clara:
Una revisión de diseño orientada a seguridad puede hacerse antes de implementar o al evolucionar una API. Algunas preguntas útiles:
La seguridad en diseño consiste en tomar decisiones estructurales que reduzcan riesgo antes de que la API llegue a producción. Versionar con disciplina, diseñar operaciones resistentes a repetición indebida y minimizar exposición no son detalles secundarios: son elecciones que determinan cuánto costará asegurar, operar y evolucionar la interfaz en el tiempo. Diseñar bien es, en gran medida, asegurar antes de implementar.
En el próximo tema estudiaremos API Gateways, WAF, proxies inversos y capas de protección, para analizar cómo ubicar controles perimetrales y de tránsito delante de la API sin perder visibilidad ni coherencia.