Korzen
Bot Protection

Auth0

Bot Protection con Auth0: una Action pre-user-registration que pregunta antes de crear el usuario, y lo que puede y no puede ver.

Auth0 ejecuta una Action antes de crear un usuario que se registra con contraseña o con un código sin contraseña (una conexión Database o Passwordless), y esa Action puede llamar a Bot Protection y rechazar el registro. La página de registro es de Auth0, en el dominio de Auth0, así que la Action no tiene cookie _kz: la decisión se apoya en la IP y el User-Agent.

El tag

Pon el tag en tus propias páginas, donde la gente llega antes de registrarse y donde inicia sesión y paga, para que esas decisiones tengan el token:

<script src="https://korzen.dev/v1/tag.js" data-site-key="YOUR_SITE_KEY" async></script>

La llamada

La Action. Auth0 le da 20 segundos en total; la llamada respeta tu timeout, y cualquier otra cosa deja pasar el registro:

// Auth0 Dashboard: Actions, Triggers, pre-user-registration; a new Action.
// Add the secret KORZEN_API_KEY to the Action.
exports.onExecutePreUserRegistration = async (event, api) => {
  let d = null;
  try {
    const res = await fetch("https://korzen.dev/v1/decide", {
      method: "POST",
      headers: { Authorization: `Bearer ${event.secrets.KORZEN_API_KEY}`, "Content-Type": "application/json" },
      body: JSON.stringify({
        ip: event.request.ip,
        user_agent: event.request.user_agent,
        ja4: event.security_context?.ja4 || undefined, // behind Cloudflare only: left out without it
        headers: { "accept-language": event.request.language },
        path: "/signup",
        method: "POST",
      }),
      signal: AbortSignal.timeout(200),
    });
    if (res.ok) d = await res.json();
  } catch {} // fail open
  if (d?.action === "block") {
    api.access.deny("korzen_block", "We could not create your account.");
    return;
  }
  // "challenge": Auth0's own CAPTCHA or MFA, if your plan has them
  if (d?.request_id) api.user.setAppMetadata("korzen_request_id", d.request_id);
};

Auth0 le da a la Action el idioma y el User-Agent del navegador, pero ninguno de los demás headers de la petición, así que la llamada reenvía solo accept-language: aquí faltan los headers que una build de navegador envía igual, que Bot Protection lee en las llamadas de tu propio servidor.

En un tenant cuyo tráfico pasa por Cloudflare (los planes Enterprise de Auth0), el evento también trae security_context.ja4: el JA4 del handshake TLS del visitante con el borde de Auth0, en la misma forma que Bot Protection lee de Cloudflare delante de tu propio servidor. La llamada lo envía como ja4 cuando está; sin él, se queda fuera.

La IP del visitante

event.request.ip es la dirección que llegó a Auth0, que ya es la del visitante: no hay nada que configurar. En un dominio propio detrás de tu proxy, mira en los ajustes de custom domain de Auth0 cómo pasar la IP del visitante.

Las decisiones de Auth0 llegan sin el token del tag. Cuando Bot Protection ya ha visto tu tag en otras páginas, que falte el token suma un poco al score (no_token), nunca lo bastante para bot por sí solo.

Actúa según la action

Lee solo action. Con block, responde con el mismo error que la acción muestra cuando falla por cualquier otro motivo, para que un bot no aprenda nada. Con challenge, usa la verificación que ya tienes (un CAPTCHA, un código por email o teléfono); si no tienes ninguna, sigue adelante. La cuenta empieza en monitor mode, donde action es siempre allow: nada cambia para los visitantes hasta que actives el block mode.

Guarda el request_id

Cada respuesta trae un request_id. Guárdalo con lo que la acción creó, en una columna de la cuenta o del pedido, o en una línea de log con su id. Sirve para identificar esa decisión cuando nos preguntes por ella y para averiguar después qué respuesta dejó entrar una cuenta falsa.

Pruébalo en tu máquina

Usa tu tenant de desarrollo. En el editor de la Action, Test la ejecuta con un evento de ejemplo; después regístrate en tu página de login, y la decisión aparece en la página Decisiones del panel, en /signup. Comprueba el fail open con un secret KORZEN_API_KEY incorrecto: el registro pasa.

Errores comunes

  • Registros con redes sociales. Google, GitHub y similares no ejecutan el trigger pre-user-registration; una Action post-login puede preguntar a Bot Protection por ellos en su primer inicio de sesión.
  • Llamar a /v1/decide desde el navegador. La API key quedaría expuesta a cada visitante; la llamada se hace desde tu servidor.
  • No poner timeout, o dejar que un error detenga el registro. Cualquier respuesta distinta de 200, o la falta de respuesta a tiempo, significa: deja pasar al visitante.