Segurança
O que está implementado
Autenticação
- PKCE obrigatório —
code_challenge exigido em todos os authorization requests
- Argon2id — senhas hasheadas com
memoryCost=19456, timeCost=2
- MFA (TOTP) — compatível com Google Authenticator, Authy
- Email OTP — verificação por código de 6 dígitos (TTL 10 min, máx 5 tentativas)
- Google OAuth — integração via Passport.js, verifica membership antes de completar login
Tokens
- RS256 — tokens assinados com chave RSA-2048 privada
- JTI revogation — tokens revogados ficam no Redis até expirar
- TTL curto — access_token expira em 10 minutos
- Refresh token rotation — cada uso gera um novo refresh_token (reuse = revogação automática)
Proteção contra ataques
- Rate limiting por IP: 20 req/60s globais em
/interaction/*
- Rate limiting por email: 10 falhas/5min → lockout; 20 falhas/60min → lockout longo
- Rate limiting password reset: 3 req/email/hora
- Rate limiting email OTP: limitado por IP
- Session fixation — oidc-provider cria nova sessão a cada fluxo
- HMAC-SHA256 em webhooks com tolerância de 5 minutos (anti-replay)
Headers HTTP
- Helmet.js — X-Frame-Options, X-Content-Type-Options, X-XSS-Protection
- HSTS — em produção (
max-age=31536000; includeSubDomains; preload)
- CSP — ativo em produção
- SameSite=Lax — cookies da sessão OIDC
Admin
- AdminGuard — verifica JWT + not-revoked +
is_admin=true + MFA
- SystemScoped — system-admins só acessam seus próprios sistemas
- Audit log — todas as ações POST/PATCH/DELETE em
/admin/* são registradas
Checklist para produção
Secrets — rotacionar antes do primeiro deploy
# Gerar JWKS key
node -e "
const jose = require('jose');
jose.generateKeyPair('RS256').then(async ({privateKey}) => {
const k = await jose.exportJWK(privateKey);
k.kid = 'sig-1'; k.alg = 'RS256'; k.use = 'sig';
console.log('JWKS_PRIVATE_KEYS=' + JSON.stringify([k]));
});
"
# Cookie keys
node -e "const c=require('crypto'); console.log('COOKIE_KEYS='+c.randomBytes(32).toString('hex')+','+c.randomBytes(32).toString('hex'))"
# Webhook secret
node -e "console.log('WEBHOOK_HMAC_SECRET='+require('crypto').randomBytes(32).toString('hex'))"
Variáveis obrigatórias em produção
NODE_ENV=production
ISSUER=https://auth.seudominio.com
ADMIN_CONSOLE_URL=https://admin.seudominio.com
CORS_ORIGINS=https://admin.seudominio.com,https://app.seudominio.com
MFA_REQUIRED=true
ADMIN_PASSWORD=<senha forte, min 12 chars>
Infraestrutura
Pós-deploy