CORS implementacao servidor: guia passo a passo
CORS parece assustador até você entender o fluxo. Neste guia, mostro como implementar CORS no servidor em passos objetivos, com dicas de erros comuns e um checklist final para você validar sua configuração.
CORS parece assustador até você entender o fluxo. Neste guia, mostro como implementar CORS no servidor em passos objetivos, com dicas de erros comuns e um checklist final para você validar sua configuração.
CORS, ou Cross-Origin Resource Sharing, é o mecanismo que o navegador usa para liberar ou bloquear requisições entre origens diferentes. Se você já viu o erro "No 'Access-Control-Allow-Origin' header is present" no console, sabe do que estou falando. Este guia mostra como implementar CORS no servidor, etapa por etapa, sem mistério.
A configuração correta depende do seu stack, mas o princípio é o mesmo: o servidor precisa declarar quais origens podem acessar os recursos, quais métodos são permitidos e como lidar com o preflight. No final, você terá um checklist para validar sua implementação.
Antes de começar, verifique os pré-requisitos: acesso ao código do servidor (ou ao proxy reverso, como Nginx), capacidade de reiniciar o serviço e um navegador com ferramentas de desenvolvedor (qualquer um serve). Você também precisa saber qual é a origem exata do seu front-end, por exemplo, https://meusite.com.br, porque é ela que vai aparecer nos headers.
Passo 1: Entenda a diferença entre requisição simples e preflight
Nem toda requisição cross-origin dispara o preflight. Requisições simples usam métodos GET, HEAD ou POST, com headers considerados seguros (como Content-Type: application/x-www-form-urlencoded) e não enviam credenciais de forma automática. Nesse caso, o navegador envia a requisição direto e só bloqueia a leitura da resposta se o header Access-Control-Allow-Origin não bater.
O preflight acontece quando você usa métodos como PUT, DELETE ou PATCH, envia headers personalizados (por exemplo, Authorization) ou usa Content-Type: application/json. O navegador primeiro envia uma requisição OPTIONS ao servidor, perguntando quais origens e métodos são aceitos. Se a resposta não autorizar, a requisição real nem chega a sair.
A especificação não define um número fixo de cenários, mas a regra prática: se você usa JSON ou tokens, prepare-se para o preflight.
Passo 2: Configure o header Access-Control-Allow-Origin
Este é o header mais importante. Ele diz ao navegador se a origem do seu front-end pode ler a resposta. Você tem duas opções: usar * (aceita qualquer origem) ou listar origens específicas.
Use * apenas para APIs públicas que não lidam com credenciais ou dados sensíveis. Se seu front-end envia cookies ou usa autenticação por header, você precisa especificar a origem exata, porque o navegador bloqueia * quando credentials: include está ativo.
No Express, por exemplo, você pode adicionar um middleware:
app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', 'https://meusite.com.br'); next(); });
O erro mais comum aqui é esquecer de incluir o protocolo completo. meusite.com.br não funciona; precisa ser https://meusite.com.br. Outro erro: usar * com credenciais, o que faz o navegador rejeitar silenciosamente.
Passo 3: Defina os métodos e headers permitidos
Além da origem, o servidor precisa declarar quais métodos HTTP são aceitos e quais headers o front-end pode enviar. Os headers Access-Control-Allow-Methods e Access-Control-Allow-Headers cuidam disso.
Para uma API REST típica, você provavelmente vai liberar GET, POST, PUT, DELETE e OPTIONS. Sobre headers: se o front-end envia Authorization ou Content-Type: application/json, eles precisam estar listados.
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
Um detalhe que muita gente descobre na prática: se você usa Authorization, não adianta permitir só Content-Type. O navegador compara exatamente o que o front-end envia com o que está no header. Se faltar um item, o preflight falha.
Passo 4: Responda corretamente ao preflight (OPTIONS)
Quando o navegador dispara o preflight, ele espera uma resposta com status 204 (No Content) ou 200, e os headers configurados nos passos anteriores. Se o servidor não tratar OPTIONS, a requisição falha com erro de CORS, mesmo que a rota exista.
No Express, você pode interceptar o OPTIONS antes das rotas:
app.options('*', (req, res) => { res.header('Access-Control-Allow-Origin', 'https://meusite.com.br'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.sendStatus(204); });
O erro comum: retornar 401 ou 403 no OPTIONS. O preflight não carrega credenciais, então ele nunca vai passar por autenticação. Trate OPTIONS como uma rota separada, sem exigir token.
Passo 5: Lide com credenciais (cookies e Authorization)
Se sua aplicação usa cookies de sessão ou autenticação por header Authorization, você precisa habilitar Access-Control-Allow-Credentials: true. Sem esse header, o navegador bloqueia a resposta mesmo que a origem esteja correta.
res.header('Access-Control-Allow-Credentials', 'true');
Atenção: quando você ativa credenciais, não pode usar * em Access-Control-Allow-Origin. A origem precisa ser explícita. Esse é um dos pontos que mais geram confusão, porque o código parece certo, mas o navegador recusa.
Outro erro comum: esquecer de configurar o withCredentials no front-end. Se o servidor permite credenciais mas o JavaScript não envia credentials: 'include' no fetch, o cookie não vai junto. A configuração precisa ser dos dois lados.
Passo 6: Teste com o navegador e com curl
Depois de configurar, teste de verdade. Abra as ferramentas de desenvolvedor, na aba Network, e faça uma requisição cross-origin. Olhe o cabeçalho da resposta: se o header Access-Control-Allow-Origin aparecer com a origem correta, o CORS está funcionando.
Para testar o preflight, use o curl para enviar uma requisição OPTIONS:
curl -X OPTIONS https://api.exemplo.com/recurso \ -H "Origin: https://meusite.com.br" \ -H "Access-Control-Request-Method: POST" \ -H "Access-Control-Request-Headers: Content-Type"
Se a resposta não incluir os headers de CORS, revise os passos 2 a 4. Um erro comum é testar só no Postman, que não aplica as regras de CORS do navegador. O Postman mostra a resposta, mas não valida se o navegador vai aceitar.
Checklist final da implementação
- [ ]
Access-Control-Allow-Origincom a origem exata (ou*sem credenciais) - [ ]
Access-Control-Allow-Methodsincluindo OPTIONS e os métodos usados - [ ]
Access-Control-Allow-HeaderslistandoContent-TypeeAuthorizationse necessário - [ ] Rota OPTIONS respondendo com 204 ou 200, sem exigir autenticação
- [ ]
Access-Control-Allow-Credentials: truesomente se você usa cookies ou tokens no header - [ ] Teste no navegador (console sem erro) e com curl para o preflight
Se você marcou todos os itens, sua API está pronta para receber requisições cross-origin. Se ainda aparecer erro, releia a mensagem do console: ela indica qual header está faltando. Na maioria dos casos, é a origem ou o método não listado.
FAQ sobre implementação de CORS
O que significa o erro "No 'Access-Control-Allow-Origin' header is present"?
Esse erro indica que o servidor não enviou o header Access-Control-Allow-Origin na resposta, ou enviou uma origem que não corresponde à do seu front-end. O navegador bloqueia a leitura da resposta para proteger o usuário. Verifique se o header está configurado e se a origem está exata, com protocolo e domínio.
CORS é uma falha de segurança do servidor?
Não. CORS é uma proteção do navegador, não do servidor. O servidor apenas declara quem pode acessar os recursos. A configuração incorreta, como liberar * com credenciais, pode criar riscos, mas o mecanismo em si existe para impedir que sites maliciosos leiam dados de outras origens sem permissão.
Preciso configurar CORS em todas as rotas?
Idealmente, sim, de forma global. Se você configurar rota por rota, é fácil esquecer uma endpoint e gerar erro intermitente. Use um middleware ou configuração global no servidor, e depois refine se alguma rota específica precisar de regras diferentes.
Qual a diferença entre CORS e CSRF?
CORS controla quem pode ler a resposta de uma requisição cross-origin. CSRF (Cross-Site Request Forgery) é um tipo de ataque que força o usuário a executar ações indesejadas. Configurar CORS corretamente ajuda a mitigar alguns vetores, mas não substitui proteções específicas contra CSRF, como tokens.
Posso usar Access-Control-Allow-Origin: * com credenciais?
Não. A especificação proíbe o uso de * quando o header Access-Control-Allow-Credentials está como true. O navegador rejeita a resposta. Você precisa listar a origem exata do front-end, mesmo que isso signifique manter uma lista de origens permitidas no servidor.
Como lidar com múltiplas origens permitidas?
Se você tem mais de uma origem (por exemplo, um domínio de produção e um de staging), o servidor precisa verificar o header Origin da requisição e responder com a origem correspondente. Não é possível enviar múltiplos valores no header. Uma solução comum é manter uma lista no servidor e usar a origem recebida se ela estiver na lista.
Letícia Sampaio Khoury
Editora de Gadgets e Consumo Tech
Testa o gadget no dia a dia real, avalia se vale a grana sem deslumbre de novidade.
Ver todos os artigos →