↓Pular para o conteúdo principal
  1. blog/
ARTIGO TÉCNICO

Não confie que sua lib de JWT funciona — teste alg:none, secret errado e token adulterado

Suíte de teste e2e criada especificamente pra verificar que a API rejeita token com secret errado, alg:none, payload adulterado, expirado e malformado — em vez de confiar que passport-jwt se comporta certo por padrão.

·3 minutos

O gap que ninguém tinha testado #

Suíte de RBAC já cobria autorização por perfil — quem pode fazer o quê. O que faltava era mais básico: nada exercitava adulteração de token contra a API real. A confiança era só “a lib de JWT deve se comportar certo por padrão” — nunca verificado com um teste de verdade.


Sanidade primeiro, sempre #

1
2
3
4
it('sanidade: o token válido de verdade autentica (garante que os
    testes abaixo não estão sempre passando por acaso)', async () => {
  // ...
});

Antes de qualquer teste de rejeição, um teste confirma que o caminho feliz funciona. Sem isso, uma suíte inteira de “rejeita X” pode estar passando porque o endpoint está quebrado pra qualquer token — inclusive o válido — e não porque a validação de segurança está funcionando.


Os 6 cenários de adulteração testados #

1
2
3
4
5
6
7
8
it('rejeita token assinado com secret errado', ...)
it('rejeita token com alg:none (sem assinatura nenhuma)', ...)
it('rejeita payload adulterado (estabelecimentoId trocado) sem
    re-assinar — assinatura não bate mais', ...)
it('rejeita token expirado', ...)
it('rejeita token malformado (lixo)', ...)
it('token de tenant não abre rota de admin de plataforma, mesmo
    assinado com o mesmo secret', ...)

O caso mais sutil da lista é o alg:none — variante clássica de ataque onde o header do JWT declara “sem algoritmo de assinatura” e algumas implementações, mal configuradas, aceitam isso como token válido sem verificar nada. Testar explicitamente que a API rejeita esse caso é diferente de assumir que a lib já cuida disso.

O teste de payload adulterado é igualmente direto ao ponto: pega um token válido, troca o estabelecimentoId no meio, sem re-assinar — a assinatura original não bate mais com o payload novo, e a API precisa rejeitar por causa disso, não por outro motivo qualquer.


Isolamento multi-tenant também é caso de segurança, não só de RBAC #

O último teste da lista não é sobre token forjado — é sobre token genuíno, assinado com o secret certo, mas de um tenant comum tentando acessar rota de administração da plataforma. Mesmo token 100% válido tecnicamente, mesma assinatura correta — e ainda assim precisa ser rejeitado, porque validade criptográfica não é a mesma coisa que autorização.


Por que isso vale mais que “confiar na lib” #

jsonwebtoken/passport-jwt são bibliotecas maduras e geralmente seguras por padrão. Mas “geralmente seguro por padrão” não é o mesmo que “seguro na configuração específica que eu escrevi” — opção mal setada, versão desatualizada, ou um middleware customizado no meio do caminho podem reabrir exatamente os buracos que essas libs foram desenhadas pra fechar. Testar contra a API real, não contra a lib isolada, é o que garante que a configuração de produção se comporta como esperado.


Tecnologias #

NestJS · jsonwebtoken · passport-jwt · Jest (e2e) · Supertest

TEM UM CENÁRIO PARECIDO?

Me chama.

Manda o contexto, os sintomas e o que já foi testado. Bora organizar as evidências antes de sair mexendo.

Falar com Castro →
Sem enrolação. Com evidência.