Ir al contenido principal
Laravel, shipping fast.

Tokens débiles, tokens que nunca caducan, tokens que se filtran, y ningún límite a los tanteos.

Aquí: un token en un archivo de log. Un token en una URL, donde acaba en el log de accesos de cada proxy. Un token emitido hace tres años para un servicio que nadie recuerda. Un cliente probando tokens tan rápido como el servidor conteste.

Qué lo impide: Sanctum genera tokens largos y aleatorios y guarda solo sus hashes. Los tokens viajan en una cabecera, nunca en la cadena de consulta, y solo por HTTPS. El Capítulo 4 pasa una caducidad en cada token y fija expiration en la configuración como red de seguridad, y nunca emite *. El log de peticiones registra el ID del token y nunca el token. Los tanteos se acotan delante de la aplicación, por dirección, como dispuso el Capítulo 6.

Cómo lo sabes: busca en tus logs el prefijo de token del Capítulo 4. No debería aparecer en ninguna parte. Lista los tokens que no se han usado en noventa días: cada uno es o un servicio que murió o una credencial a la espera de que alguien la encuentre.

Hay una comprobación que vale la pena hacer a mano. Emite un token, bórralo y llama a la API con él. La respuesta debe ser un 401 al instante. Si alguna vez añades caché delante de la autenticación, este es el test que te dice a qué renunciaste.

3. Autorización rota a nivel de propiedad de objeto

A quien llama se le permite tocar el registro, pero no ese campo. Dos direcciones: leer una propiedad que no debería ver, y escribir una que no debería fijar.

Aquí, al leer: settings en un consumidor, que guarda un token de proveedor, y webhook_secret.

Aquí, al escribir: un consumidor que envía "rate_limit": 100000 o "settings": {...} en un PATCH a su propio registro.

Qué lo impide: a la salida, el Resource. ConsumerResource nombra los campos que salen, y ninguno de los dos secretos está entre ellos. El modelo marca ambos como Hidden, como segunda cerradura. A la entrada, el FormRequest y Fillable: validated() contiene solo campos que tienen reglas, y ninguno de los dos secretos es asignable en bloque. #[FailOnUnknownFields] del Capítulo 5 va más lejos y convierte el intento en un 422.

Pero mira de cerca rate_limit y license_limit. Sí están en UpdateConsumerRequest, porque un operador necesita cambiarlos. Si un consumidor corriente pudiera llegar alguna vez a update sobre su propio registro, podría subirse sus propios límites. Hoy update exige la habilidad del operador, así que el agujero está cerrado. Pero lo cierra un atributo en el controlador y no el request, y ese es el tipo de cosa que una revisión existe para notar. El día que alguien deje a los consumidores editar su propia dirección de contacto, la clase de request tiene que partirse en dos.

Cómo lo sabes: el test assertJsonMissingPath('data.settings') del Capítulo 5, y su espejo para la escritura: envía un campo prohibido y comprueba que la base de datos no cambió. (Documentación de Laravel: Eloquent: Getting Started › Mass Assignment.)

No se pudo cargar el audio. Inténtalo de nuevo en un momento.