Korzen
Bot Protection

Proteger un checkout

Rutas de pago, inicio de sesión y registro: exige el token del tag en Node, Go, Python, PHP, Java, .NET o en un Cloudflare Worker, empieza en modo monitor y conoce a quién frena.

La prueba de tarjetas (card testing) es un script que prueba tarjetas robadas con pagos pequeños, uno tras otro, para saber cuáles siguen funcionando. Por lo general el script nunca carga tu página. El tag nunca se ejecuta, así que la decisión no tiene ninguna señal de un navegador, y su clase es unknown, que se deja pasar. La falta de una señal nunca es evidencia de bot, así que Bot Protection no lo llama así. En las acciones que busca un script así, pide una prueba de una visita real: el token del tag.

Qué hace requireToken

Con "require_token": true en la llamada (la opción requireToken de los SDKs, en Go RequireToken), la acción solo sigue con un token válido que el tag obtuvo en ese navegador. Sin él, la respuesta es challenge con token_required true, sea cual sea la clase; la clase en sí no cambia. El envío del formulario gasta el token, una vez por sesión y por ruta cada hora; hasta tres intentos en dos minutos son el mismo intento, así que una tarjeta rechazada y una segunda tarjeta siguen pasando. Una carga de página (GET, HEAD) no gasta token, y los SDKs envían la opción solo con las acciones. Las reglas completas: una acción que necesita el tag.

Pon el tag en la página donde empieza cada acción: la página de checkout, la de inicio de sesión, la de registro. El tag

Qué rutas

  • Pago: el envío que cobra la tarjeta o confirma el pedido, y cualquiera que añada una tarjeta o canjee una tarjeta regalo. Prueba de tarjetas.
  • Inicio de sesión: el envío que comprueba la contraseña. Credential stuffing.
  • Registro: el envío que crea la cuenta. Cuentas falsas.

Déjala fuera de las rutas a las que no lleva ninguna página tuya: los webhooks de tu proveedor de pagos, la API de tu app móvil, el servidor de un socio. Ahí no se ejecuta ningún tag, así que cada solicitud recibiría un desafío.

En tu código

Cada pestaña lo añade a la llamada que monta la guía de su framework. Node y Go usan la opción del archivo cliente que sirve Korzen; los demás envían el campo en el cuerpo de la llamada.

Node

// Express, with korzen.js as the Express guide sets it up
const guard = protect({ client: korzen, ip: (_get, req) => req.ip, requireToken: true });

app.get("/checkout", guard, showCheckout); // the page: a page load spends no token
app.post("/checkout", guard, placeOrder); // the action: it needs the tag's token

// Next.js, Hono or any handler of a Web Request
export const POST = withKorzen(placeOrder, { client, ip: ipFrom.vercel, requireToken: true });

Go

mux.Handle("POST /checkout", bot.Protect(http.HandlerFunc(placeOrder), korzen.Options{
	IP:           korzen.RemoteIP,
	RequireToken: true, // the action needs the tag's token
}))

Python

# In decide() of the Django and Flask or FastAPI guide: one more field in the body.
json={
    # ...the fields the guide sends
    "path": path,
    "method": "POST",
    "require_token": True,  # on payment, login and sign-up
},

PHP

// In decide() of the PHP or Laravel guide: one more field in the body.
'path' => $path,
'method' => 'POST',
'require_token' => true, // on payment, login and sign-up

Java

// In decide() of the Spring Boot guide: one more field in the body.
body.put("path", path);
body.put("method", "POST");
body.put("require_token", true); // on payment, login and sign-up

.NET

// In Decide() of the ASP.NET Core guide: one more field in the body.
["path"] = path,
["method"] = "POST",
["require_token"] = true, // on payment, login and sign-up

Ruby

# In decide of the Rails guide: one more field in the body.
path: path,
method: "POST",
require_token: true # on payment, login and sign-up

Cloudflare Worker

# wrangler.toml: the paths whose actions need the tag's token, by commas;
# one ending in * is a prefix.
[vars]
KORZEN_REQUIRE_TOKEN = "/checkout,/login,/signup"

Cuando la misma función pregunta por todas las acciones, dale la elección: pasa true desde los handlers de pago, inicio de sesión y registro y false desde los demás. Un campo mal escrito, como requireToken en el cuerpo, se rechaza con 400 y deja pasar al visitante, como cualquier error: revisa las primeras respuestas.

Primero el modo monitor

Actívala mientras la cuenta está en modo monitor. La action de cada respuesta sigue siendo allow, así que no se frena a nadie; una acción que llegó sin token responde intended_action challenge con token_required true. Sigue dos cifras durante unos días:

  • las decisiones en esas rutas con token_required true, en las respuestas que registra tu servidor;
  • la proporción Sin token en la salud de la integración, en la página Configuración. Una proporción alta ahí suele indicar una página que lleva a la acción sin el tag, o un formulario enviado antes de que el tag se ejecute: corrige eso primero.

Lo que queda son sobre todo scripts, y algunas personas cuyo navegador no ejecuta el tag (abajo). Activa el modo bloqueo cuando esa proporción te parezca aceptable. Modo monitor y modo bloqueo

Las acciones de cada clase

Los valores por defecto sirven para un checkout. La acción de la clase y el token son cosas distintas: con un token válido, la acción es la de la clase; sin él, es como mínimo challenge.

ClaseAcciónEn un checkout
human highallowsigue
humanallowsigue
unknownallowsigue: con el token exigido, un script que se saltó tu página recibe challenge
botchallengetu propia verificación, como 3-D Secure o un código por email, o nuestra página de desafío desde la página de checkout
bot highblockrechaza con el mensaje de una tarjeta rechazada, para que el script no aprenda nada

Con el señuelo activado para bot y bot_high en la página Configuración, los SDKs responden por sí solos a una acción con señuelo, con algo que parece un éxito, para que el script no aprenda nada. Una respuesta señuelo

Después del pago, envía el resultado de tu proveedor de pagos como feedback: un chargeback o un fraude confirmado pesan en contra de las próximas decisiones de ese navegador, un buen cliente pesa a favor.

A quién frena

Un visitante cuyo navegador no ejecuta el tag no tiene token: un bloqueador de anuncios o una extensión de privacidad que lo bloquea, un filtro DNS que bloquea el host de la API de Bot Protection, JavaScript desactivado. En una ruta con require_token, en modo bloqueo, ese visitante recibe un desafío en la acción. Nuestra página de desafío pide una pequeña prueba de trabajo y que nuestro tag se ejecute allí. Con JavaScript desactivado no hay forma de pasar, y un filtro DNS que bloquea nuestro host bloquea también la página. Esa persona no puede pagar, salvo que le des otro camino.

  • Envíala en las rutas donde un script te cuesta más que una persona frenada: pago, inicio de sesión, registro. Nunca en todas las rutas.
  • Mira la proporción en modo monitor antes de activar el modo bloqueo, como arriba.
  • Bajo challenge, ofrece un camino que no necesite nuestro tag, si tienes uno: 3-D Secure, un código por email o por teléfono, un contacto de soporte. El hook onChallenge de los SDKs lo ejecuta en lugar de la redirección.

Cuando Bot Protection va lento o está caído, tu servidor deja pasar al visitante, con token o sin él: la llamada es fail-open.