Toda chamada à API ASO exige headers:
X-Aso-Public-Key: pk_a1b2c3...
X-Aso-Timestamp: 1730820000000
X-Aso-Nonce: hex16random
X-Aso-Signature: HMAC-SHA256(secret_key, METHOD|PATH|TIMESTAMP|NONCE|BODY_SHA256)
const crypto = require('crypto');
const PK = process.env.ASO_PUBLIC_KEY;
const SK = process.env.ASO_SECRET_KEY;
async function asoVerify(req) {
const r = await fetch('https://SEU-DOMINIO/v3/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
remoteip: req.ip,
method: req.method,
path: req.path,
ua: req.headers['user-agent'],
headers: req.headers,
}),
});
return r.json(); // { action, score, reason }
}
app.use(async (req, res, next) => {
const v = await asoVerify(req);
if (v.action === 'deny') return res.status(403).json({ error: 'blocked', score: v.score });
if (v.action === 'challenge') return res.status(429).json({ error: 'challenge_required', score: v.score });
next();
});
O middleware aso-edge bloqueia/desafia o bot na borda, sem
sobrecarregar nem a sua origem nem a ASO. Visitante já aprovado é verificado
localmente pelo cookie de clearance (HMAC, sem rede); só o primeiro
contato chama a ASO; sob flood o deny fica em cache O(1).
Os 3 níveis de bot: Naive (curl/python/Go) → deny · Basic-stealth (Chrome UA falso sem client-hints completos) → deny/challenge · Humanizado (headers perfeitos, sem JS) → challenge obrigatório.
const asoEdge = require('./aso-edge');
const express = require('express');
const app = express();
app.use(asoEdge({
publicKey: process.env.ASO_PUBLIC_KEY, // pk_...
edgeKey: process.env.ASO_EDGE_KEY, // GET /v1/edge/key (verifica clearance local)
endpoint: 'https://SEU-DOMINIO',
mode: 'enforce', // 'enforce' | 'monitor'
}));
app.use(express.json());
app.post('/__aso_clear', asoEdge.clearanceRoute({
publicKey: process.env.ASO_PUBLIC_KEY,
endpoint: 'https://SEU-DOMINIO',
}));
app.get('/', (req, res) => res.send('conteúdo protegido'));
app.listen(3000);
Como absorve sem sobrecarregar: sua origem nunca vê o bot (bloqueado no
middleware); a ASO só é chamada no primeiro contato — cada visitante bom
é verificado local pelo cookie por 30 min. Código e opções em
sdk/aso-edge.js + sdk/README.md.
POST /v1/auth/signup — criar contaPOST /v1/auth/login — login (retorna sessionToken)POST /v1/auth/logout — encerrar sessãoGET /v1/auth/me — dados da contaPOST /v1/keys/generate — gerar par PK/SK · body aceita mode e rateLimitGET /v1/keys/list — listar chaves (devolve mode + rateLimit de cada)POST /v1/keys/update — atualizar mode e/ou rateLimit de uma keyPOST /v1/plan/select — escolher planoPOST /v3/verify — veredito L7/L4 (allow/challenge/deny)POST /v3/edge/check — decisão de borda (absorve antes da origem): allow+clearance / challenge / denyGET /v1/edge/key — edgeKey p/ o middleware verificar o clearance localmenteGET /v3/challenge?mode=… · POST /v3/challenge — caixa "sou humano" (emite/valida PASS token)POST /v1/protection/mode — troca o modo (aso-captcha-v3 / v2 / aso-invisible-v1)POST /v3/under-attack — liga/desliga Under Attack ModeGET /v3/capabilities — matriz de capacidadesGET /v3/dashboard/summary — métricas + feedGET /health — health checkTudo do 3.7 mais:
Nós protegemos contra L7 (HTTP/HTTPS). Para ataques volumétricos L3/L4 (até Tbps) recomendamos uma camada superior no edge — Cloudflare, Akamai ou AWS Shield — à frente da ASO. Grátis no lançamento.
# Qualquer host Node (processo contínuo): build npm install · start npm start
# healthcheck: /health
# Defina o segredo de assinatura (estável entre deploys):
ASO_SIGNING_SECRET = $(openssl rand -hex 32)
# E a persistência remota (contas/chaves sobrevivem a deploys):
ASO_STATE_HTTP_URL / ASO_STATE_HTTP_TOKEN / ASO_STATE_HTTP_METHOD / ASO_STATE_HTTP_FORMAT
Estrutura do projeto:
server.js → servidor HTTP persistente (entrypoint)public/ → site estático (landing, login, dashboard, docs, demo)netlify/functions/ → os endpoints (despachados pelo server.js)netlify/lib/aso.js → núcleo de proteção L7/L4 (13 camadas)Persistência: é um processo Node contínuo — o estado de proteção (ban, reputação, threat score, volumétrico L4) persiste durante toda a vida do processo, ao contrário do serverless que zera no cold start.