No puedes publicar una API sin pensar en seguridad. Y la buena noticia es que la seguridad no requiere arquitectura compleja. Requiere patrones consistentes y aplicados.
Este capítulo construye un sistema de seguridad de nivel producción usando patrones simples y probados aplicados en todas partes. Sin teorías, sin abstracciones complejas. Entenderás cómo funcionan los tokens Bearer sin estado, por qué cachearlos importa para el rendimiento, cómo el middleware impone seguridad en cada capa, qué hace efectivo un límite de frecuencia y cómo validar peticiones en la frontera para que los datos malos nunca lleguen a tus controladores.
Un principio guía todo: la seguridad es un valor por defecto, no una funcionalidad opcional. La autenticación no es algo que añades después. El límite de frecuencia no es algo que recuerdas. La validación de dominio no es algo que esperas. Todo está integrado. Sigue los patrones de este capítulo y la seguridad se vuelve automática, embebida en tu arquitectura, aplicada en todas partes sin excepción.
Por que tokens Bearer
Antes de implementarlos, respondamos a la pregunta obvia: ¿por qué este enfoque?
Esta API es de servicio a servicio, no de cara al usuario. No hay «inicio de sesión». No hay sesiones, ni autenticación por cookies, ni perfiles. Lo que hay son sistemas de backend llamando a esta API para gestionar licencias. La llama un sistema de despliegue. La llama un sistema de facturación. La llaman otros microservicios. Esos llamantes necesitan autenticación, pero de un tipo completamente distinto al de un usuario web.
OAuth 2.0 y Laravel Sanctum son excelentes para APIs de cara al usuario. Manejan suplantación de usuarios, tokens de acceso personales, autenticación de SPAs —toda la complejidad de representar seres humanos individuales. Pero aquí no necesitamos nada de eso. Necesitamos un mecanismo ultrasimple: demuestra que tienes un token válido y obtienes acceso.
El paquete ryangjchandler/bearer de Ryan Chandler resuelve exactamente este problema. Es mínimo: un modelo de token, hashing básico, gestión de expiración, y ya. Sin conceptos de usuario. Sin estado de sesión. Sin flujos complicados. Sólo búsqueda y validación de tokens sin estado.
Una excepción a la consistencia con el framework: notarás que a lo largo de esta guía insistimos en seguir las convenciones de Laravel y usar sus soluciones integradas. La autenticación es la única excepción intencionada. ¿Por qué? Porque elegir la herramienta correcta importa más que elegir una herramienta de Laravel. Sanctum viene con Laravel y resuelve problemas importantes. Pero resuelve un problema distinto del que tenemos. Usar «correctamente» la herramienta equivocada es peor que usar bien la correcta. Si forzáramos el modelo de autenticación basado en usuarios de Sanctum a un contexto de servicio a servicio, estaríamos peleando con el framework en lugar de fluir con él. En su lugar elegimos un paquete mínimo y hecho a propósito que encaja perfectamente con nuestras necesidades, y lo extendemos siguiendo patrones de Laravel. Esto no es rebeldía frente al framework: es pragmatismo.
Elegimos este paquete sobre Sanctum por tres razones:
Uno: hecho a propósito. Sanctum asume que construyes una aplicación multiusuario con autenticación de usuarios. Su complejidad lo refleja. Los tokens Bearer del paquete de Chandler están diseñados exactamente para peticiones de servicio a servicio, donde los tokens representan sistemas, no personas.
Dos: evitar complejidad. Sanctum te obliga a pensar en tokens de acceso personales, suplantación y sesiones de SPA. Nada de eso aplica aquí. Cuantos menos conceptos tengas que llevar en la cabeza, menos errores introducirás.
Tres: flexibilidad. Extendemos el modelo Token de Chandler para añadir nuestro propio modelo Bearer con propiedades como settings y domains. Las asunciones del modelo de usuario de Sanctum nos pelearían en cada paso.
La verdad cruda es esta: la mayoría de los fallos de seguridad no vienen de que falte infraestructura compleja. Vienen de la inconsistencia y de casos límite olvidados. Un sistema simple aplicado en todas partes gana a un sistema complejo aplicado de forma inconsistente.