Trilha 11 · Como um navegador funciona

Segurança: Same-Origin Policy e CORS

Por que um site não pode ler dados de outro? A Política de Mesma Origem protege usuários, e CORS é o mecanismo oficial para quebrar essa barreira de forma segura.

① Intuição

Por que origens precisam ser isoladas

Imagine que você abre banco.com e em outra aba abre site-malicioso.com. Sem proteção, o JavaScript do site malicioso poderia fazer requests para banco.com usando seus cookies de sessão — lendo seu saldo, transferindo dinheiro. A Same-Origin Policy (SOP) impede isso: JavaScript só pode ler respostas da mesma origem.

Mas APIs legítimas precisam ser acessadas de outras origens. O CORS (Cross-Origin Resource Sharing) permite que o servidor autorize explicitamente origens específicas via headers HTTP. O browser fiscaliza — não o servidor nem o cliente JS.

CORS não é segurança do servidor — é proteção do usuário no browser. Uma requisição de um servidor backend para outro não tem CORS (não tem browser). CORS só existe em requests feitas pelo JavaScript no browser.
② Visualização interativa

Simule uma requisição cross-origin

Configure a origem, o destino, o método e se o servidor inclui CORS headers. Veja passo a passo por que a requisição é permitida ou bloqueada.

Origem (o seu site)
Destino (API que você chama)
Método HTTP
Content-Type
Configure a requisição e clique em Enviar para simular.
③ Explicação técnica

A Política de Mesma Origem

# Same-Origin Policy (SOP) — a regra fundamental

# Origem = protocolo + host + porta
https://meuapp.com:443          # origem A
https://meuapp.com:443/pagina   # mesma origem (path não conta)
http://meuapp.com:443           # DIFERENTE — protocolo diferente
https://api.meuapp.com:443      # DIFERENTE — subdomínio diferente
https://meuapp.com:8080         # DIFERENTE — porta diferente

# O que a SOP protege:
# JavaScript de origem A não pode ler resposta de origem B
# Exceto: <img src="B">, <script src="B">, <link href="B"> (leitura bloqueada)

# O que CORS faz:
# Permite que B autorize explicitamente A via headers HTTP

Headers CORS

# Headers CORS que o servidor precisa retornar

# Requisição simples (GET, POST form-data, text/plain)
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://meuapp.com   # ou * para todos

# Requisição não-simples — requer preflight OPTIONS primeiro
OPTIONS /api/dados HTTP/1.1
Origin: https://meuapp.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://meuapp.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400    # cache do preflight por 24h

# Com credenciais (cookies) — * não funciona, precisa ser explícito
Access-Control-Allow-Origin: https://meuapp.com
Access-Control-Allow-Credentials: true
Outras proteções do browser: CSP (Content Security Policy) — header que especifica de onde recursos podem ser carregados (script-src 'self' bloqueia scripts externos não autorizados). XFO (X-Frame-Options) — impede que seu site seja embutido em iframe de outro domínio, prevenindo clickjacking. Ambos são configurados no servidor e fiscalizados pelo browser.
④ Projeto para programar

Configure CORS em um servidor

Mini projeto: crie uma API com Express.js e use o pacote cors para permitir apenas requisições de localhost:3000. Teste com fetch de origens diferentes e observe o erro no console do browser.

Projeto principal: implemente CORS manualmente (sem pacote): intercepte o header Origin, compare com uma allowlist, e adicione os headers de resposta corretos para GET simples e para POST JSON (com preflight). Teste requisições com e sem credenciais.

Desafio extra: configure uma Content Security Policy para uma página HTML: permita scripts apenas do próprio domínio (script-src 'self'), imagens de CDN específico, e bloqueie inline scripts. Use o Report-Only mode para monitorar violações sem bloquear.

⑤ Exercícios rápidos

Teste sua intuição

Quando CORS bloqueia uma requisição cross-origin, o que exatamente acontece?
Qual tipo de requisição cross-origin exige um preflight OPTIONS?
Uma aplicação Node.js fazendo fetch para outra API Node.js precisa configurar CORS?
⑥ Aplicações no mundo real

Onde você encontra isso

🌐

APIs públicas

APIs públicas (OpenWeather, GitHub, Stripe) precisam retornar Access-Control-Allow-Origin: * ou com autenticação por API Key. Sem isso, nenhum app frontend conseguiria consumi-las.

🔐

OAuth e cookies

Login com Google envolve redirects entre origens. O token de acesso é passado via parâmetro de URL, não via fetch direto, justamente para contornar CORS. Com credenciais (cookies), credentials: 'include' e headers exatos são obrigatórios.

🛡️

CSP em produção

Sites grandes como GitHub usam CSP estrito: script-src 'nonce-abc123' — só scripts com o nonce correto (gerado no servidor a cada request) executam. Bloqueia XSS mesmo se o atacante injetar HTML.

🔗

Reverse proxy

Uma solução comum para evitar problemas de CORS em dev: usar Nginx ou Vite como proxy — as requests vão para localhost:3000/api que internamente faz forward para api.outro.com. O browser vê sempre a mesma origem.

← Anterior: O Event Loop Próxima: Performance →