O que é CORS

CORS significa Cross-Origin Resource Sharing, ou Compartilhamento de Recursos de Origem Cruzada. É uma política de segurança implementada pelos navegadores que controla como páginas web podem fazer requisições para domínios diferentes do próprio site.

A história começa com a Same-Origin Policy, criada nos anos 90 para proteger usuários. Essa política impede que um script rodando em "site-a.com" acesse dados de "site-b.com" sem permissão explícita. CORS é o mecanismo que permite flexibilizar essa regra de forma controlada e segura.

Por que está tão em pauta agora? Porque a arquitetura moderna separou frontend e backend em domínios diferentes. É raro hoje ter frontend e API no mesmo domínio. Resultado: todo projeto web moderno precisa entender e configurar CORS corretamente.

Como funciona

Quando seu JavaScript faz uma requisição para um domínio diferente, o navegador adiciona automaticamente um header chamado Origin com o domínio atual. O servidor precisa responder com o header Access-Control-Allow-Origin informando quais origens são permitidas.

Para requisições simples (GET ou POST com Content-Type texto), o fluxo é direto. Para requisições complexas (DELETE, PUT, ou POST com JSON), o navegador faz primeiro uma requisição preflight usando o método OPTIONS para verificar se a operação é permitida antes de enviar a requisição de verdade.

É fundamental entender: CORS é implementado pelo navegador, não pelo servidor. Se você fizer a mesma requisição via curl ou Postman, ela vai funcionar sem CORS. O bloqueio acontece apenas quando o código roda no browser.

Principais headers CORS

Os headers mais importantes que você precisa conhecer são:

  • Access-Control-Allow-Origin: define qual origem pode acessar. Pode ser "*" (todos) ou um domínio específico como "https://meusite.com.br".
  • Access-Control-Allow-Methods: lista os métodos HTTP permitidos (GET, POST, PUT, DELETE, OPTIONS).
  • Access-Control-Allow-Headers: define quais headers o cliente pode enviar, como Authorization e Content-Type.
  • Access-Control-Allow-Credentials: define se cookies e tokens de autenticação podem ser incluídos. Se for true, o Allow-Origin não pode ser "*".
  • Access-Control-Max-Age: por quantos segundos o resultado do preflight pode ser cacheado pelo browser.

Entender cada header evita horas de debugging. O erro mais comum é usar "*" com credentials, combinação que o browser bloqueia por segurança.

Como configurar CORS passo a passo

CORS é configurado no servidor (backend), nunca no frontend. Aqui estão as situações mais comuns:

No .NET Core (ASP.NET): em Program.cs, adicione builder.Services.AddCors() com a política desejada e depois app.UseCors("NomeDaPolitica"). Defina quais origens são permitidas com .WithOrigins("https://meusite.com.br") combinado com .AllowAnyHeader().AllowAnyMethod().

No Node.js com Express: instale o pacote cors com npm e adicione app.use(cors({ origin: 'https://meusite.com.br' })). Para múltiplas origens, passe um array ou uma função de validação.

No NGINX: adicione os headers diretamente na configuração com add_header Access-Control-Allow-Origin e trate requisições OPTIONS retornando status 204 sem body.

Exemplo prático: Angular consumindo API .NET

Imagine um frontend em "https://app.meusite.com.br" consumindo uma API em "https://api.meusite.com.br". Subdomínios diferentes contam como origens diferentes, então CORS é necessário mesmo sendo o mesmo domínio raiz.

No backend .NET, a configuração correta seria algo como:

builder.Services.AddCors(options => {   options.AddPolicy("Frontend", policy => {     policy.WithOrigins("https://app.meusite.com.br")           .AllowAnyHeader()           .AllowAnyMethod()           .AllowCredentials();   }); }); // depois do builder.Build(): app.UseCors("Frontend");

No frontend Angular, você não precisa de configuração especial. O browser cuida de tudo automaticamente. Se aparecer o erro "has been blocked by CORS policy" no console, o problema está sempre no backend, nunca no Angular.

Comparação com outras abordagens

Antes do CORS existir como padrão, desenvolvedores usavam JSONP (JSON with Padding) para burlar a Same-Origin Policy. A técnica explorava o fato de que tags script não têm restrição de origem. Era uma gambiarra, só funcionava com GET e abria vulnerabilidades. Hoje é considerado legado e deve ser evitado.

Outra abordagem válida é usar um proxy reverso para servir frontend e backend sob o mesmo domínio. Com NGINX, você roteia "/api/*" para o backend e o restante para o frontend. Isso elimina o CORS completamente, mas adiciona complexidade de infraestrutura.

CORS é o padrão correto para arquiteturas modernas com domínios separados. É seguro, bem documentado e suportado por todos os navegadores atuais.

Pontos positivos e limitações

Pontos positivos: CORS é uma camada de segurança real. Impede que sites maliciosos façam requisições autenticadas em nome do usuário em outras APIs sem permissão. É padronizado pelo W3C, implementado nativamente nos browsers e não requer bibliotecas extras no frontend.

Limitações: A configuração pode ser confusa, especialmente quando envolve credentials e múltiplas origens. As mensagens de erro no console são genéricas e nem sempre indicam o problema exato. A requisição preflight adiciona uma chamada HTTP extra antes de cada requisição complexa.

Um erro muito comum é tentar resolver CORS no frontend com extensões de browser ou flags de desenvolvimento. Isso pode funcionar localmente mas nunca resolve em produção. A solução correta é sempre configurar o backend adequadamente.

Casos de uso reais

SPA com API separada: todo projeto com React, Angular ou Vue consumindo uma API REST em outro domínio precisa de CORS. É o cenário mais comum no desenvolvimento web moderno.

Microsserviços: quando o frontend chama diretamente serviços diferentes em subdomínios distintos, como um serviço de autenticação, um de produtos e outro de pagamentos, cada um precisa ter CORS configurado para a origem do frontend.

CDN e assets externos: quando fontes, imagens ou scripts são servidos de um domínio diferente, CORS é necessário. As fontes do Google Fonts, por exemplo, já têm CORS configurado nos servidores do Google.

APIs públicas: serviços como Google Maps, Stripe e Firebase configuram CORS para permitir chamadas do browser de qualquer origem, com restrições de chave de API no lado do servidor.

Dicas e boas práticas

Nunca use Access-Control-Allow-Origin: * combinado com Access-Control-Allow-Credentials: true. O browser rejeita essa combinação por segurança e você vai perder tempo tentando entender o erro. Se precisar de credentials, especifique a origem exata.

Em produção, sempre liste as origens exatas que podem acessar sua API. Use uma variável de ambiente com as origens permitidas e carregue no startup da aplicação. Isso facilita configurar origens diferentes para desenvolvimento e produção.

Durante o desenvolvimento local, use um proxy configurado no bundler para evitar problemas de CORS. O Angular CLI tem a opção proxy.conf.json para isso. O Vite tem a opção proxy no vite.config.ts. Isso mantém a configuração de produção correta e simplifica o desenvolvimento.

Vale a pena entender CORS?

Sim, absolutamente. CORS não é opcional para quem trabalha com desenvolvimento web moderno. Vai aparecer em todo projeto que separa frontend de backend, e não entender como funciona vai gerar horas de debugging desnecessário ao longo da carreira.

O investimento para entender é pequeno. Leia a documentação do MDN sobre CORS (é excelente e tem versão em português), experimente configurar no seu framework e você vai resolver qualquer problema em minutos da próxima vez que aparecer.

O próximo passo prático: se você tem um projeto com erro de CORS agora, aplique o que aprendeu aqui e configure os headers corretos no backend. Se não tem, crie um projeto simples com frontend e backend em portas diferentes e experimente configurar do zero.