Teste de cartões (card testing) é um script que tenta cartões roubados com pagamentos pequenos, um atrás do outro, para descobrir quais ainda funcionam. Em geral o script nunca carrega a sua página. A tag nunca roda, então a decisão não tem nenhum sinal de um navegador, e a classe é unknown, que é liberada. A falta de um sinal nunca é evidência de bot, então o Bot Protection não o chama assim. Nas ações que esse script procura, peça a prova de uma visita de verdade: o token da tag.
O que o requireToken faz
Com "require_token": true na chamada (a opção requireToken dos SDKs, em Go RequireToken), a ação só segue com um token válido obtido pela tag naquele navegador. Sem ele, a resposta é challenge com token_required true, qualquer que seja a classe; a classe em si não muda. O envio do formulário gasta o token, uma vez por sessão e por rota a cada hora; até três tentativas em dois minutos são a mesma tentativa, então um cartão recusado e um segundo cartão ainda passam. Um carregamento de página (GET, HEAD) não gasta token, e os SDKs enviam a opção só nas ações. As regras completas: uma ação que precisa da tag.
Coloque a tag na página onde cada ação começa: a página de checkout, a de login, a de cadastro. A tag
Quais rotas
- Pagamento: o envio que cobra o cartão ou fecha o pedido, e qualquer um que adicione um cartão ou resgate um vale-presente. Teste de cartões.
- Login: o envio que confere a senha. Credential stuffing.
- Cadastro: o envio que cria a conta. Contas falsas.
Deixe de fora as rotas às quais nenhuma página sua leva: os webhooks do seu provedor de pagamento, a API do seu app mobile, o servidor de um parceiro. Nenhuma tag roda ali, então toda requisição receberia desafio.
No seu código
Cada aba acrescenta a opção à chamada que o guia do framework monta. Node e Go usam a opção do arquivo cliente que a Korzen serve; os outros enviam o campo no corpo da chamada.
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"
Quando a mesma função pergunta por todas as ações, dê a ela a escolha: passe true dos handlers de pagamento, login e cadastro e false dos demais. Um campo com erro de digitação, como requireToken no corpo, é recusado com 400 e deixa o visitante passar, como todo erro: confira as primeiras respostas.
Primeiro o modo monitor
Ligue a opção enquanto a conta está no modo monitor. A action de toda resposta continua allow, então ninguém é barrado; uma ação que chegou sem token responde intended_action challenge com token_required true. Acompanhe dois números por alguns dias:
- as decisões nessas rotas com
token_requiredtrue, nas respostas que o seu servidor registra; - a parcela Sem token na saúde da integração, na página Configuração. Uma parcela alta ali costuma indicar uma página que leva à ação sem a tag, ou um formulário enviado antes de a tag rodar: corrija isso primeiro.
O que sobra é sobretudo script, e algumas pessoas cujo navegador não roda a tag (abaixo). Ligue o modo bloqueio quando essa parcela for aceitável para você. Modo monitor e modo bloqueio
As ações de cada classe
O padrão serve para um checkout. A ação da classe e o token são coisas separadas: com um token válido, a ação é a da classe; sem ele, é no mínimo challenge.
| Classe | Ação | Num checkout |
|---|---|---|
| human high | allow | siga |
| human | allow | siga |
| unknown | allow | siga: com o token exigido, um script que pulou a sua página recebe challenge |
| bot | challenge | a sua própria verificação, como 3-D Secure ou um código por email, ou a nossa página de desafio a partir da página de checkout |
| bot high | block | recuse com a mensagem de um cartão recusado, para o script não aprender nada |
Com a isca ligada para bot e bot_high na página Configuração, os SDKs respondem sozinhos a uma ação com isca, com algo que parece sucesso, para o script não aprender nada. Uma resposta isca
Depois do pagamento, envie o resultado do seu provedor de pagamento como feedback: um chargeback ou uma fraude confirmada pesam contra as próximas decisões daquele navegador, um bom cliente pesa a favor.
Quem isso barra
Um visitante cujo navegador não roda a tag não tem token: um bloqueador de anúncios ou uma extensão de privacidade que a bloqueia, um filtro de DNS que bloqueia o host da API do Bot Protection, o JavaScript desligado. Numa rota com require_token, no modo bloqueio, esse visitante recebe desafio na ação. A nossa página de desafio pede uma pequena prova de trabalho e que a nossa tag rode ali. Com o JavaScript desligado não há como passar, e um filtro de DNS que bloqueia o nosso host bloqueia a página também. Essa pessoa não consegue pagar, a menos que você ofereça outro caminho.
- Envie a opção nas rotas em que um script custa mais do que uma pessoa barrada: pagamento, login, cadastro. Nunca em todas as rotas.
- Leia a parcela no modo monitor antes de ligar o modo bloqueio, como acima.
- Sob
challenge, ofereça um caminho que não precise da nossa tag, se você tiver um: 3-D Secure, um código por email ou telefone, um contato do suporte. O hookonChallengedos SDKs o executa no lugar do redirecionamento.
Quando o Bot Protection está lento ou fora do ar, o seu servidor deixa o visitante passar, com token ou sem: a chamada é fail-open.