Le test de cartes (card testing) est un script qui essaie des cartes volées avec de petits paiements, l'un après l'autre, pour trouver celles qui marchent encore. Le plus souvent, le script ne charge jamais votre page. Le tag ne s'exécute jamais, donc la décision n'a aucun signal d'un navigateur, et sa classe est unknown, qui passe. Un signal absent n'est jamais la preuve d'un bot, donc Bot Protection ne le qualifie pas ainsi. Sur les actions que vise un tel script, demandez plutôt la preuve d'une vraie visite : le token du tag.
Ce que fait requireToken
Avec "require_token": true dans l'appel (l'option requireToken des SDK, en Go RequireToken), l'action ne continue qu'avec un token valide obtenu par le tag dans ce navigateur. Sans token, la réponse est challenge avec token_required à true, quelle que soit la classe ; la classe elle-même ne change pas. L'envoi du formulaire dépense le token, une fois par session et par chemin chaque heure ; jusqu'à trois essais en deux minutes sont le même essai, donc une carte refusée puis une deuxième carte passent toujours. Un chargement de page (GET, HEAD) ne dépense aucun token, et les SDK n'envoient l'option qu'avec les actions. Les règles complètes : une action qui demande le tag.
Placez le tag sur la page d'où part chaque action : la page de checkout, la page de connexion, la page d'inscription. Le tag
Quelles routes
- Paiement : l'envoi qui débite la carte ou passe la commande, et tout envoi qui ajoute une carte ou utilise une carte cadeau. Le test de cartes.
- Connexion : l'envoi qui vérifie le mot de passe. Le credential stuffing.
- Inscription : l'envoi qui crée le compte. Les faux comptes.
Laissez-la de côté sur les routes vers lesquelles aucune de vos pages ne mène : les webhooks de votre prestataire de paiement, l'API de votre application mobile, le serveur d'un partenaire. Aucun tag ne s'y exécute, donc chaque requête recevrait un défi.
Dans votre code
Chaque onglet l'ajoute à l'appel que le guide de son framework met en place. Node et Go prennent l'option du fichier client que Korzen fournit ; les autres envoient le champ dans le corps de l'appel.
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"
Quand la même fonction interroge pour toutes les actions, laissez-lui le choix : passez true depuis les handlers de paiement, de connexion et d'inscription, et false depuis les autres. Un champ mal orthographié, comme requireToken dans le corps, est refusé avec 400 et laisse passer le visiteur, comme toute erreur : vérifiez les premières réponses.
D'abord le mode surveillance
Activez-la pendant que le compte est en mode surveillance. L'action de chaque réponse reste allow, donc personne n'est arrêté ; une action arrivée sans token répond intended_action challenge avec token_required à true. Suivez deux chiffres pendant quelques jours :
- les décisions sur ces routes avec
token_requiredà true, dans les réponses que votre serveur journalise ; - la part Sans token dans la santé de l'intégration, sur la page Configuration. Une part élevée y signale le plus souvent une page sans tag qui mène à l'action, ou un formulaire envoyé avant que le tag ait tourné : corrigez cela d'abord.
Ce qui reste, ce sont surtout des scripts, et quelques personnes dont le navigateur n'exécute pas le tag (plus bas). Activez le mode blocage quand cette part vous semble acceptable. Mode surveillance et mode blocage
Les actions de chaque classe
Les valeurs par défaut conviennent à un checkout. L'action de la classe et le token sont distincts : avec un token valide, l'action est celle de la classe ; sans token, c'est au moins challenge.
| Classe | Action | Sur un checkout |
|---|---|---|
| human high | allow | continuer |
| human | allow | continuer |
| unknown | allow | continuer : avec le token exigé, un script qui a sauté votre page reçoit challenge |
| bot | challenge | votre propre vérification, comme 3-D Secure ou un code par e-mail, ou notre page de défi depuis la page de checkout |
| bot high | block | refuser avec le message d'une carte refusée, pour que le script n'apprenne rien |
Avec le leurre activé pour bot et bot_high sur la page Configuration, les SDK répondent d'eux-mêmes à une action leurrée par ce qui ressemble à un succès, pour que le script n'apprenne rien. Une réponse leurre
Après le paiement, envoyez le résultat de votre prestataire de paiement en feedback : un chargeback ou une fraude confirmée abaisse les prochaines décisions pour ce navigateur, un bon client les relève.
Qui cela arrête
Un visiteur dont le navigateur n'exécute pas le tag n'a pas de token : un bloqueur de publicités ou une extension de confidentialité qui le bloque, un filtre DNS qui bloque l'hôte de l'API de Bot Protection, JavaScript désactivé. Sur une route avec require_token, en mode blocage, ce visiteur reçoit un défi sur l'action. Notre page de défi demande une petite preuve de travail et que notre tag s'y exécute. Sans JavaScript, il n'y a aucun moyen de passer, et un filtre DNS qui bloque notre hôte bloque aussi la page. Cette personne ne peut pas payer, sauf si vous lui offrez un autre chemin.
- Envoyez-la sur les routes où un script vous coûte plus qu'une personne arrêtée : paiement, connexion, inscription. Jamais sur toutes les routes.
- Lisez la part en mode surveillance avant d'activer le mode blocage, comme plus haut.
- Sous
challenge, proposez un chemin qui ne demande pas notre tag, si vous en avez un : 3-D Secure, un code par e-mail ou par téléphone, un contact du support. Le hookonChallengedes SDK l'exécute à la place de la redirection.
Quand Bot Protection est lent ou indisponible, votre serveur laisse passer le visiteur, avec ou sans token : l'appel est fail-open.