Pular para o conteúdo principal

CORS e origens permitidas

Uma chave publicável pode conter uma lista de origens permitidas: os sites que podem usá-la. Esta página explica onde essa lista é verificada, o que o navegador mostra quando uma verificação falha e o que a lista não protege.

Uma origem é composta pelo esquema, host e porta de uma página, por exemplo, https://www.example.com ou http://localhost:3000. Ela não inclui um caminho.

A lista é opcional​

Uma chave publicável funciona com uma lista vazia. Uma lista vazia significa que qualquer origem pode usar a chave. Esse é o estado de uma chave criada sem origens definidas, e você pode limpar a lista posteriormente.

Adicione as origens antes de colocar uma chave em um site de produção. Com uma lista definida, uma cópia da sua chave colada na página de outra pessoa deixa de funcionar ali. As proteções oferecidas e suas limitações são explicadas abaixo.

As chaves de servidor ignoram a lista. Uma chave de servidor nunca pode ser usada em um navegador, independentemente do conteúdo da lista.

Como escrever uma entrada​

RegraExemplo
Somente esquema, host e porta opcional. Não inclua caminho, consulta nem barra final.https://www.example.com, não https://www.example.com/
https é obrigatório. http é aceito apenas para localhost, 127.0.0.1 e [::1]. A página de chaves de API não aceita [::1]; configure-o pela API de gerenciamento de chaves.http://localhost:3000
A correspondência é exata. Não há caracteres curinga, e cada subdomínio é uma origem diferente. Uma entrada contendo * é salva como foi escrita e não corresponde a nenhum site.https://example.com e https://www.example.com são duas entradas
A porta faz parte da origem. Omita as portas padrão (443 para https, 80 para http).https://example.com, não https://example.com:443
Até 100 entradas por chave. Entradas duplicadas são rejeitadas.

As entradas são armazenadas em letras minúsculas, sem as portas padrão, para corresponder ao que o navegador envia.

Uma página aberta do disco (file://) não tem uma origem que possa ser adicionada. Durante o desenvolvimento, sirva a página em http://localhost.

Defina a lista na página de chaves de API em kaleidr.com/api-keys ou com allowed_origins na API de gerenciamento de chaves.

Onde a lista é verificada​

EtapaVerificaçãoEm caso de falha
1. Troca de sessãoO cabeçalho Origin da requisição deve estar na lista da chave, quando houver uma lista definida.403 origin_not_allowed. Nenhuma sessão é emitida. Uma requisição sem o cabeçalho Origin retorna 403 origin_required.
2. Cada chamada em execuçãoUm token de sessão funciona apenas na origem para a qual foi emitido.403 session_origin_mismatch.
3. Cada chamada em execuçãoA origem da sessão deve continuar na lista da chave.401. Remover uma origem da chave encerra as sessões já emitidas para ela.
4. Requisições de mapa-base com chaveO Editor incorporado envia sua chave publicável nas requisições a https://tile.kaleidr.com para o estilo, os sprites e as fontes. O site da página deve constar na lista da chave para que ela seja reconhecida.A requisição é tratada como se não tivesse chave e pode ser recusada com 429 tile_access_restricted.
5. A respostaA API só adiciona Access-Control-Allow-Origin quando a credencial é válida e a origem é permitida.O navegador impede que a página leia a resposta.

A etapa 5 é o comportamento normal do CORS e explica por que as falhas aparecem dessa maneira no navegador.

Requisição de verificação prévia​

Antes de um POST entre sites com corpo JSON, o navegador envia uma requisição de verificação prévia OPTIONS. A Kaleidr responde a todas com 204 e reflete a origem solicitante, porque a verificação prévia não contém credenciais e não pode ser comparada a uma chave. A lista é aplicada à requisição real.

Cabeçalho da resposta de verificação préviaValor
Access-Control-Allow-MethodsGET, POST, OPTIONS
Access-Control-Allow-HeadersAuthorization, Content-Type, Accept, X-Api-Key, X-Request-Id
Access-Control-Max-Age600

Uma requisição que envie qualquer outro cabeçalho falha na verificação prévia do navegador. Não adicione cabeçalhos personalizados às chamadas feitas de uma página.

Em uma resposta permitida, a API também envia Access-Control-Expose-Headers: Retry-After, X-Request-Id, para que o código da página possa ler esses dois cabeçalhos. Ela nunca envia Access-Control-Allow-Credentials: a API não usa cookies.

O que aparece quando uma origem é recusada​

Quando a origem ou a credencial é recusada, a resposta não tem o cabeçalho Access-Control-Allow-Origin. O navegador então oculta a resposta do código da página. Portanto, a página não vê o corpo da resposta 401 ou 403: ela recebe um erro de rede.

No console:

Access to fetch at 'https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions' from origin
'https://www.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource.

seguido de um erro do SDK contendo [kaleidr:chat] (ou o produto que você montou). Nada é exibido.

Para encontrar a causa real, abra a guia Rede do navegador, selecione a requisição sessions e leia o status e a resposta:

Status e código na guia RedeCausaCorreção
403 origin_not_allowedA origem desta página não está na lista da chave.Adicione exatamente a origem mostrada no cabeçalho Origin da requisição.
401 Invalid or missing API keyA chave foi digitada incorretamente, revogada ou expirou.Confira a chave na página de chaves de API.
403 server_key_in_browserUma chave de servidor foi enviada de uma página.Use uma chave publicável na página. Faça a rotação da chave de servidor.
403 session_origin_mismatchUm token de sessão foi usado em uma origem diferente daquela que o solicitou.Faça a troca da sessão na página que vai utilizá-la.
A verificação prévia falha, nenhum POST apareceA requisição enviou um cabeçalho fora da lista permitida.Remova o cabeçalho personalizado.

Depois que a credencial e a origem são aceitas, os erros posteriores podem ser lidos pela página e não causam erro CORS. Uma chave válida nessa origem, mas sem permissão para o produto, falha na troca com 403 legível (product_not_allowed, insufficient_scope ou tier_capability_not_allowed), e o SDK registra kaleidr session exchange failed (403). Uma resposta 429 de uma sessão válida chega com o corpo e o cabeçalho Retry-After. Os códigos são explicados em Autenticação e escopos.

A mesma requisição nunca mostra um erro CORS quando executada em um terminal, pois CORS é uma regra do navegador. Isso torna o curl uma maneira rápida de verificar o par chave-origem:

curl -i https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions \
-H "X-Api-Key: kld_pk_live_…" \
-H "Origin: https://www.example.com" \
-H "Content-Type: application/json" \
-d '{"product":"chat"}'

Uma origem permitida retorna 200 com access-control-allow-origin: https://www.example.com. Uma origem recusada retorna 403 {"detail":"origin_not_allowed"} sem esse cabeçalho.

Por que uma chave de servidor é recusada no navegador​

Uma chave de servidor é um segredo permanente. Qualquer pessoa que a possua pode chamar a API em nome da sua organização até que você a revogue. O código-fonte de uma página é público; portanto, uma chave de servidor incluída na página é uma chave vazada.

A Kaleidr a recusa em três pontos:

  1. O SDK rejeita uma chave kld_sk_… ao montar, com um erro no console e sem requisição de rede.
  2. A API responde 403 server_key_in_browser a qualquer requisição com chave de servidor que contenha um cabeçalho Origin.
  3. A resposta não contém cabeçalho CORS; portanto, o código da página não conseguiria lê-la de qualquer maneira.

Nenhuma dessas medidas desfaz o vazamento. O CORS bloqueia a resposta, não a requisição: quando a API a recusa, a chave já foi enviada e está visível para quem examinar a página. Se uma chave de servidor foi incluída em uma página, faça a rotação dela.

A lista não mantém a chave em segredo​

Os navegadores definem o cabeçalho Origin corretamente, mas outros clientes não precisam fazer isso. Um script, uma ferramenta de linha de comando ou um servidor pode enviar qualquer Origin, como demonstra o exemplo de curl acima. Portanto:

  • A lista impede que outros sites usem sua chave nos navegadores dos visitantes deles. Essa é sua função, e ela a cumpre bem.
  • A lista não impede um solicitante determinado que copie sua chave publicável e envie requisições usando sua origem fora de um navegador.

Planeje-se considerando isso. Trate tudo o que uma chave publicável consegue acessar como disponível a qualquer pessoa que possa ler sua página:

  • Limite a exposição da cota usando um teto mensal por chave e o limite de taxa da chave. Consulte Cotas e limites de taxa.
  • Não adicione o escopo vendor a uma chave publicável, a menos que os dados acessados por ela sejam dados que você publicaria nessa página. Consulte Autenticação e escopos.
  • Use uma chave por site para poder revogar uma sem afetar os demais.

Veja uma explicação mais completa no modelo de segurança.

Credenciais em URLs​

As chamadas à API da plataforma carregam a credencial em um cabeçalho, nunca em uma URL. As requisições de mapa-base feitas pelas incorporações da Kaleidr são a única exceção: elas incluem uma credencial do navegador na URL da requisição, onde ela pode aparecer no histórico do navegador e nos logs de rede. Isso é aceitável para uma credencial publicável, que já é pública, mas nunca para uma chave de servidor. Não coloque kld_sk_… em nenhuma URL.

Alterando a lista​

  • Adicionar uma origem passa a valer na próxima troca de sessão feita por essa origem. Requisições de mapa-base podem levar alguns minutos para reconhecer a alteração.
  • Remover uma origem recusa novas trocas feitas por ela e encerra as sessões existentes na próxima requisição.
  • Limpar a lista volta a permitir “qualquer origem”.

Páginas relacionadas​