c.IP() detrás del proxy del hosting devuelve la IP interna del contenedor que reenvía (10.x.x.x). Contra eso, ninguna IP pública cargada en una llave podía coincidir: toda API key con restricción de IP daba 403, que es exactamente lo que le pasó a la integración de vCard. Ahora se lee X-Forwarded-For, y se toma la ÚLTIMA entrada, no la primera: con un proxy adelante esa es la que escribió el proxy. Si quien llama manda su propio X-Forwarded-For, el proxy le agrega la IP real al final — quedarse con la primera sería dejar que cada uno declare su IP y la restricción no valdría nada. El test fija ese caso. Mismo arreglo en la autenticación de Pagos Externos, que comparaba igual. El 403 ahora dice qué IP se vio y cuál está permitida: sin eso, del otro lado se prueba a ciegas. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
34 lines
1.2 KiB
Go
34 lines
1.2 KiB
Go
package middlewares
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
|
|
)
|
|
|
|
// AuthServicioPago protege los endpoints públicos de la API de pagos externos
|
|
// (/api/v1/pagos-externos/*). Es independiente de la sesión/JWT interna: el
|
|
// caller es una aplicación de un tercero que solo tiene un token largo
|
|
// (Bearer) y opcionalmente está restringido a una o varias IPs/CIDRs. Si pasa,
|
|
// deja el *models.ServicioPagoExterno resuelto en Locals("servicio_pago").
|
|
func AuthServicioPago(c *fiber.Ctx) error {
|
|
auth := c.Get("Authorization")
|
|
token := strings.TrimSpace(strings.TrimPrefix(auth, "Bearer "))
|
|
if token == "" || token == auth {
|
|
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": true, "message": "Falta el header Authorization: Bearer <token>"})
|
|
}
|
|
|
|
servicio, err := models.FindServicioPagoExternoActivoByToken(token)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": true, "message": "Token inválido o servicio inactivo"})
|
|
}
|
|
|
|
if !servicio.IPPermitida(IPDelCliente(c)) {
|
|
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": true, "message": "IP no autorizada para este servicio"})
|
|
}
|
|
|
|
c.Locals("servicio_pago", servicio)
|
|
return c.Next()
|
|
}
|