Front-end e back-end: domínios, proxy e o erro de CORS

CONTEÚDO TBF HOST

Front-end e back-end: domínios, proxy e o erro de CORS

Existe uma mensagem de erro que todo desenvolvedor que separa front-end e back-end encontra mais cedo ou mais tarde: o navegador recusa a chamada à API, com uma explicação sobre política de origem que não parece fazer sentido — porque a API está funcionando, e chamá-la por outra ferramenta funciona.

Esse erro não é um defeito. É uma proteção do navegador operando exatamente como deveria. E a forma como você resolve tem consequências que vão além de fazer a chamada passar: ela afeta autenticação, cookies, segurança e a complexidade da sua infraestrutura.

Este guia explica o mecanismo e compara as formas de organizar os endereços.

Por que o navegador bloqueia

O conceito por trás é chamado de política de mesma origem, e ele existe por um motivo concreto.

Uma origem é a combinação de protocolo, domínio e porta. Duas páginas têm a mesma origem quando esses três elementos coincidem exatamente. Qualquer diferença — inclusive entre um domínio e um subdomínio dele — cria origens distintas.

A regra: uma página de uma origem não pode ler livremente respostas de outra origem.

O motivo fica claro com um exemplo. Sem essa proteção, um site malicioso aberto em outra aba poderia fazer chamadas ao sistema do seu banco usando a sua sessão ativa e ler as respostas. A política de mesma origem impede isso.

O mecanismo que permite exceções controladas é o que se costuma chamar de CORS: o servidor de destino declara quais origens têm permissão para ler as respostas dele. Sem essa declaração, o navegador bloqueia — mesmo que a requisição tenha chegado e sido respondida com sucesso.

Dois esclarecimentos que evitam confusão:

  • Não é uma proteção do servidor, é do navegador. Chamar a mesma API por outra ferramenta funciona normalmente, porque não há navegador aplicando a regra.
  • Permitir uma origem não é uma falha de segurança, desde que seja uma origem que você controla. O problema é permitir qualquer origem indiscriminadamente.

As formas de organizar os endereços

A decisão que determina se você vai lidar com isso ou não:

ArranjoExemploMesma origem?Precisa de CORS?
Mesmo domínio, caminho diferentesite.com e site.com/apiSimNão
Subdomíniosite.com e api.site.comNãoSim
Domínio separadosite.com e outra.comNãoSim
Portas diferentessite.com e site.com:3000NãoSim

A primeira linha é a que resolve o problema pela raiz: se o front-end e a API respondem no mesmo domínio, em caminhos diferentes, não há origens distintas e nada precisa ser configurado.

Isso é feito com um proxy reverso na frente: ele recebe todas as requisições e encaminha internamente — as que começam com um caminho específico vão para a aplicação de back-end, as demais para os arquivos do front-end. Para o navegador, tudo veio do mesmo lugar.

A última linha costuma surpreender: portas diferentes são origens diferentes, o que explica por que o erro aparece em desenvolvimento mesmo com tudo rodando na mesma máquina.

Comparando os arranjos

Cada um tem vantagens reais, e a escolha não é óbvia.

Mesmo domínio, via proxy

A favor: sem configuração de origens cruzadas, cookies funcionam naturalmente, um único certificado, uma configuração a menos para manter errada.

Contra: exige um proxy reverso configurado, e front-end e back-end ficam acoplados no mesmo ponto de entrada.

Subdomínio para a API

A favor: separação clara, possibilidade de hospedar cada parte em lugares diferentes, escalabilidade independente.

Contra: exige configuração de origens permitidas, e cookies precisam de atenção especial — embora subdomínios do mesmo domínio principal tenham mais opções que domínios totalmente distintos.

Domínio separado

A favor: independência total, útil quando a API atende vários produtos ou clientes.

Contra: a configuração mais trabalhosa, com as maiores restrições para cookies e autenticação.

A recomendação prática: para um produto único, o mesmo domínio via proxy é o arranjo mais simples e com menos pontos de falha. Subdomínio faz sentido quando as partes precisam ser hospedadas ou escaladas de forma independente. Domínio separado, quando a API é um produto por si só.

Autenticação: onde a decisão pesa

O ponto que transforma uma escolha de organização em uma decisão de arquitetura.

Existem duas formas comuns de manter a sessão de um usuário, e elas reagem de forma diferente à separação de origens:

Cookies. São enviados automaticamente pelo navegador e podem ser configurados de modo que o código da página não consiga lê-los, o que os protege contra uma classe de ataques. Mas o comportamento entre origens diferentes é restritivo: navegadores vêm limitando progressivamente o envio de cookies entre sites distintos.

Credencial guardada pela aplicação. O código guarda um identificador de sessão e o envia manualmente a cada chamada. Funciona entre quaisquer origens, mas o valor fica acessível ao código da página — e, se houver uma falha que permita execução de código de terceiros, ele pode ser roubado.

A consequência prática:

  • Mesmo domínio via proxy permite usar cookies protegidos sem complicação. É o arranjo mais seguro e o mais simples ao mesmo tempo.
  • Subdomínios do mesmo domínio principal permitem cookies com configuração adequada, com algum cuidado.
  • Domínios separados tornam o uso de cookies progressivamente mais difícil, empurrando para a segunda abordagem.

Este é o argumento mais forte a favor do arranjo de mesmo domínio: ele não é apenas mais simples de configurar — ele permite a estratégia de autenticação mais segura.

Erros comuns e o que eles significam

SituaçãoCausa provável
Erro aparece só no navegadorComportamento esperado da política de origem
Funciona em desenvolvimento, falha em produçãoOrigem de produção não declarada
Chamadas simples passam, outras nãoFalta permissão para o método ou cabeçalho usado
Cookie não é enviadoFalta configuração específica para credenciais
Erro após adicionar um cabeçalhoCabeçalho não está na lista de permitidos
Falha intermitenteOrigens declaradas de forma inconsistente

A terceira linha explica um comportamento que confunde: algumas chamadas passam sem qualquer configuração e outras não. Requisições consideradas simples pelo navegador são enviadas diretamente; as demais são precedidas de uma verificação de permissão, e é nessa verificação que a maior parte dos erros aparece.

A quarta merece nota: permitir a origem não basta para que cookies sejam enviados — existe uma configuração adicional específica para isso, tanto do lado do servidor quanto na chamada feita pelo front-end. É a causa mais comum de “a chamada passa mas o usuário aparece como não autenticado”.

O que não fazer

Três atalhos que resolvem o sintoma e criam problemas:

Permitir qualquer origem. É a solução que aparece primeiro em qualquer busca e a mais perigosa: ela autoriza qualquer site a fazer chamadas à sua API e ler as respostas. Em uma API pública sem dados sensíveis, pode ser aceitável. Em uma API com autenticação, não é.

Desativar a proteção no navegador durante o desenvolvimento. Resolve localmente e esconde o problema até a publicação — quando ele reaparece em produção, com pressa.

Usar um serviço externo que repassa as chamadas. Além de adicionar um intermediário desnecessário, significa enviar o tráfego da sua aplicação por terceiros.

A alternativa correta em desenvolvimento é usar o recurso de encaminhamento que as ferramentas de build oferecem, que simula o arranjo de mesma origem localmente — o que tem a vantagem adicional de aproximar o ambiente de desenvolvimento do de produção.

O que configurar no servidor

Quando a separação de origens for a escolha, os pontos de atenção:

  1. Declare origens específicas, e não qualquer uma.
  2. Liste os métodos que a API efetivamente usa.
  3. Liste os cabeçalhos que as chamadas enviam, incluindo os de autenticação.
  4. Habilite o envio de credenciais explicitamente, se usar cookies.
  5. Responda corretamente à verificação prévia, que o navegador envia antes das chamadas não simples.
  6. Defina um tempo de cache para essa verificação, evitando uma requisição extra a cada chamada.
  7. Trate ambientes separadamente, com as origens de desenvolvimento, homologação e produção declaradas conforme o caso.

O item 6 tem impacto de desempenho perceptível: sem ele, cada chamada não simples vira duas requisições — a verificação e a chamada em si. Em uma interface com muitas chamadas, isso dobra o número de idas ao servidor.

E o item 7 merece disciplina: declarar a origem de desenvolvimento em produção é um descuido comum e desnecessário.

Onde isso se encaixa na arquitetura

Vale situar a decisão no conjunto.

Se o seu front-end é servido como arquivos estáticos e a API é uma aplicação separada, o proxy reverso na frente resolve dois problemas de uma vez: elimina a questão de origens e centraliza o ponto de entrada, com HTTPS, compressão e controle de acesso em um lugar só.

Essa é a mesma peça de infraestrutura tratada nos artigos sobre aplicações Node.js em produção e sobre onde hospedar uma aplicação React — e é um dos motivos pelos quais aplicações com front-end e back-end separados pedem um ambiente com controle sobre a configuração do servidor.

Conclusão

O erro de origem cruzada não é um defeito a contornar: é uma proteção do navegador funcionando. A pergunta certa não é como desativá-la, e sim como organizar os endereços da aplicação.

A resposta mais simples resolve o problema pela raiz: servir front-end e API no mesmo domínio, em caminhos diferentes, com um proxy reverso encaminhando internamente. Sem origens distintas, não há o que configurar — e, como bônus, é o arranjo que permite a estratégia de autenticação mais segura.

Se a separação for necessária, declare origens específicas em vez de permitir qualquer uma, e lembre que habilitar o envio de cookies exige configuração própria além da permissão de origem. Conheça o Cloud Server para React da TBF Host e avalie o ambiente adequado à arquitetura do seu projeto.

Perguntas frequentes

O que é o erro de CORS?

É o navegador bloqueando a leitura de uma resposta vinda de uma origem diferente da página. Origem é a combinação de protocolo, domínio e porta — qualquer diferença cria origens distintas. O servidor de destino precisa declarar quais origens têm permissão para ler suas respostas.

Por que a chamada funciona em outra ferramenta e falha no navegador?

Porque a política de mesma origem é aplicada pelo navegador, não pelo servidor. A requisição chega e é respondida normalmente; o navegador é que impede a página de ler a resposta. Ferramentas de linha de comando ou clientes de API não aplicam essa regra.

Como evitar o problema de CORS de vez?

Servindo o front-end e a API no mesmo domínio, em caminhos diferentes, com um proxy reverso encaminhando internamente. Sem origens distintas, não há nada a configurar — e esse arranjo ainda permite usar cookies protegidos, que é a estratégia de autenticação mais segura.

Subdomínio conta como mesma origem?

Não. Origem é protocolo, domínio e porta exatos, então um subdomínio é uma origem diferente do domínio principal. Isso exige configuração de origens permitidas — embora subdomínios do mesmo domínio principal tenham mais opções para cookies que domínios totalmente distintos.

Por que algumas chamadas passam e outras não?

Porque requisições consideradas simples pelo navegador são enviadas diretamente, enquanto as demais são precedidas de uma verificação de permissão. A maior parte dos erros aparece nessa verificação — normalmente por falta de autorização para o método ou para algum cabeçalho enviado.

A chamada passa mas o usuário aparece como não autenticado. Por quê?

Provavelmente falta a configuração específica para envio de credenciais. Permitir a origem não basta: é preciso habilitar explicitamente o envio de cookies, tanto no servidor quanto na chamada feita pelo front-end. É a causa mais comum desse sintoma.

Posso permitir qualquer origem na minha API?

Em uma API pública sem dados sensíveis nem autenticação, pode ser aceitável. Em uma API autenticada, não — isso autoriza qualquer site a fazer chamadas e ler as respostas. É a solução que aparece primeiro em qualquer busca e a mais perigosa.

Como resolver o erro durante o desenvolvimento?

Usando o recurso de encaminhamento que as ferramentas de build oferecem, que simula o arranjo de mesma origem localmente. Desativar a proteção no navegador resolve só na sua máquina e esconde o problema até a publicação, quando ele reaparece com pressa.

Facebook
X
LinkedIn