Desvendando o InvalidClientTokenId no AWS SES com Node.js e TypeScript: Aprendi uma lição que a “ordem dos fatores” importa sim.
Marcelo Magario

Marcelo Magario @marcelomagario

About: Back-end Developer | AWS CCP

Location:
São Paulo
Joined:
May 30, 2025

Desvendando o InvalidClientTokenId no AWS SES com Node.js e TypeScript: Aprendi uma lição que a “ordem dos fatores” importa sim.

Publish Date: May 31
0 0

Desenvolver APIs é sempre um aprendizado, e por vezes nos deparamos com erros que, à primeira vista, parecem apontar para um lugar, mas a causa raiz está em outro.

Recentemente, ao integrar o AWS SES (Simple Email Service) no meu projeto pessoal de backend Node.js com TypeScript, me deparei com o frustrante erro InvalidClientTokenId. Este post detalha o problema, o processo de depuração e a solução.

O Cenário do Problema

Eu estava construindo o backend para o formulário de contato do meu portfólio pessoal. A ideia era que, ao preencher o formulário no frontend, o backend enviasse um e-mail para mim usando o AWS SES. Minha aplicação era construída com Node.js, TypeScript e Express.js, utilizando o @aws-sdk/client-ses para a comunicação com a AWS e o dotenv para gerenciar as variáveis de ambiente.
As credenciais da AWS (Access Key ID e Secret Access Key) estavam devidamente configuradas no meu arquivo .env, junto com a região da AWS e os e-mails de origem e destino para o SES. Minhas políticas de IAM na AWS garantiam acesso total ao SES para o usuário correspondente, e a identidade do e-mail de origem estava devidamente verificada na região correta do SES.

Tudo parecia estar em ordem, mas ao testar a rota de envio de e-mails, o servidor retornava uma mensagem de erro genérica. Ao inspecionar os logs detalhados do backend, a mensagem era clara:

InvalidClientTokenId: The security token included in the request is invalid..

A Persistência do Erro e a Confusão Inicial

Este erro da AWS geralmente indica que as credenciais de autenticação são inválidas ou estão ausentes. Naturalmente, minhas primeiras ações foram:

1. Verificar o .env: Confirmei que as chaves estavam lá, sem erros de digitação ou espaços extras.
2. Revisitar o IAM na AWS: Verifiquei se o usuário tinha as permissões corretas (inclusive com o AmazonSESFullAccess) e se a chave de acesso que eu estava usando no .env estava ativa no console da AWS.
3. Checar o AWS SES: Confirmei que o e-mail de origem estava verificado e que a região do SES correspondia à que estava no meu arquivo de variáveis de ambiente.

Apesar de todas as verificações apontarem que "estava tudo certo", o erro persistia. Tentei gerar novas chaves de acesso no IAM, apagar caches de credenciais locais que poderiam existir, mas a teimosia do InvalidClientTokenId continuava.

A Revelação Inesperada: undefined

A chave para desvendar o mistério veio quando decidi inspecionar o que o cliente do SES realmente estava "vendo" em tempo de execução. Adicionei um log estratégico no meu controller, exatamente no ponto onde o cliente SES era inicializado, para imprimir o valor da Access Key ID que estava sendo utilizada.

A saída foi chocante e reveladora: SES Client Access Key ID being used: undefined.

Isso significava que, embora a variável AWS_ACCESS_KEY_ID estivesse no meu arquivo .env e eu soubesse que ela era lida em algum momento, no instante em que o cliente SES estava sendo configurado, essa variável simplesmente não existia no ambiente do processo.

A Causa Raiz: A Ordem Importa!

O problema não estava nas credenciais em si, nem na falta de permissões, mas sim na ordem em que as coisas eram carregadas no meu aplicativo Node.js.

Em ambientes JavaScript com módulos (como o TypeScript é transpilado), as instruções de import no topo de um arquivo são processadas e seus módulos são executados antes que o restante do código do arquivo principal comece. No meu app.ts, a chamada para dotenv.config() (que carrega as variáveis do .env para process.env) estava posicionada abaixo das minhas declarações de import.

  1. Meu app.ts importava a rota de contato.
  2. A rota de contato, por sua vez, importava o controller de contato.
  3. Quando o controller de contato era carregado e o cliente do SES era inicializado (uma ação que acontece no momento da importação do módulo), o dotenv.config() no app.ts ainda não havia sido executado.
  4. Consequentemente, as variáveis de ambiente essenciais da AWS ainda não estavam disponíveis em process.env.
  5. O cliente SES era instanciado com valores undefined para as credenciais, e a AWS naturalmente as rejeitava com o erro InvalidClientTokenId.

A Solução Definitiva

A solução foi simples, mas de impacto: mover a linha dotenv.config(); para o topo absoluto do meu arquivo app.ts, garantindo que ela fosse a primeira coisa a ser executada.

Com essa pequena, mas crucial, alteração, as variáveis de ambiente eram carregadas no process.env antes que qualquer outro módulo que dependesse delas fosse inicializado. O cliente SES, então, conseguia acessar as credenciais corretas, se autenticar com sucesso na AWS, e os e-mails começaram a ser entregues sem problemas.

Lições Aprendidas

Este problema reforçou algumas lições importantes no desenvolvimento de APIs:

1. A Ordem de Carregamento é Crucial: Em Node.js e TypeScript, a sequência de execução de módulos e inicializações pode ter um impacto significativo. Variáveis de ambiente precisam ser carregadas antes que qualquer código que as utilize seja executado.
2. Debug com console.log: Uma ferramenta simples como console.log pode ser incrivelmente poderosa para inspecionar o estado das variáveis e o fluxo de execução em um ponto específico do código.
3. Confie nos Logs, mas Depure o Contexto: O erro InvalidClientTokenId apontava para credenciais, e elas estavam corretas no .env. O desafio foi entender por que elas não estavam acessíveis no momento certo. O erro da AWS estava correto, mas a causa não era o valor da chave, e sim sua ausência no ambiente de execução.

Esta experiência foi um ótimo lembrete de como nuances no fluxo de execução de um aplicativo podem levar a desafios de depuração complexos, mas também de como uma abordagem sistemática e a inspeção direta do ambiente podem levar à solução.

Comments 0 total

    Add comment