As solicitações HTTP contêm cabeçalhos como "User-Agent" ou "Content-Type". Além dos cabeçalhos anexados pelos
navegadores, os apps Android podem adicionar outros cabeçalhos, como cookie ou referenciador, usando o extra da intent
EXTRA_HEADERS
. Por motivos de segurança, o Chrome filtra alguns dos cabeçalhos extras,
dependendo de como e onde uma intent é iniciada.
As solicitações de origem cruzada exigem uma camada extra de segurança, já que o cliente e o servidor não são de propriedade da mesma parte. Este guia aborda como iniciar essas solicitações usando guias personalizadas do Chrome, ou seja, intents iniciadas em apps que abrem um URL na guia do navegador. Até o Chrome 83, os desenvolvedores podiam adicionar qualquer cabeçalho ao iniciar uma guia personalizada. Da versão 83 em diante, o Chrome começou a filtrar todos os cabeçalhos de origem cruzada, exceto nenhuma aprovação, porque os que não eram aprovados cria um risco à segurança. A partir do Chrome 86, é possível anexar cabeçalhos não aprovados a solicitações de origem cruzada quando o servidor e o cliente estiverem relacionados usando um Digital Asset Link. Esse comportamento está resumido na tabela abaixo:
Versão do Chrome | Cabeçalhos CORS permitidos |
---|---|
Antes do Chrome 83 | aprovado, não aprovado |
Chrome 83 ao Chrome 85 | incluído na lista de aprovação |
do Chrome 86 em diante | "Aprovada", "Não aprovado" quando um Digital Asset Link está configurado |
Tabela 1: Filtragem de cabeçalhos CORS não aprovados na lista.
Neste artigo, mostramos como configurar uma conexão verificada entre o servidor e o cliente e usá-la para enviar cabeçalhos HTTP aprovados e não listados. Pule para o artigo Como adicionar cabeçalhos extras a intents de guia personalizadas para ver o código.
Contexto
Cabeçalhos de solicitação de CORS da lista de aprovação x não aprovados
O Compartilhamento de recursos entre origens (CORS, na sigla em inglês) permite que um aplicativo da Web de uma origem solicite recursos de outra origem. A lista de cabeçalhos CORS-APPROVElisting é mantida no padrão HTML. Confira exemplos de cabeçalhos aprovados na próxima tabela:
Cabeçalho | Descrição |
---|---|
Aceitar-idioma | anuncia linguagens naturais que o cliente entende |
content-language | descreve a linguagem destinada ao público atual |
content-type | indica o tipo de mídia do recurso |
Tabela 2: Exemplo de cabeçalhos CORS da lista de aprovação.
Os cabeçalhos da lista de aprovação são considerados seguros porque não contêm informações confidenciais do usuário e provavelmente não farão com que o servidor execute operações possivelmente prejudiciais.
Confira na tabela a seguir exemplos de cabeçalhos não aprovados na lista:
Cabeçalho | Descrição |
---|---|
token do portador | autentica o cliente em um servidor |
origin | indica a origem da solicitação |
biscoito | contém cookies definidos pelo servidor |
Tabela 3: Exemplo de cabeçalhos CORS não aprovados.
O padrão HTML não recomenda anexar cabeçalhos não aprovados às solicitações CORS, e os servidores presumem que as solicitações de origem cruzada contêm apenas cabeçalhos aprovados. O envio de cabeçalhos não aprovados de domínios de origem cruzada permite que apps de terceiros maliciosos criem cabeçalhos que usam cookies do usuário que o Chrome ou outro navegador armazena e anexa às solicitações. Eles podem autenticar transações maliciosas do servidor que, de outra forma, não seriam possíveis.
Como anexar cabeçalhos da lista de aprovação do CORS às solicitações de guias personalizadas
As guias personalizadas são uma maneira especial de abrir páginas da Web em uma guia personalizada do navegador. As intents de guia
personalizada podem ser criadas usando CustomTabsIntent.Builder()
. Também é possível anexar cabeçalhos a essas
intents usando um Bundle
com a sinalização Browser.EXTRA_HEADERS
:
CustomTabsIntent intent = new CustomTabsIntent.Builder(session).build();
Bundle headers = new Bundle();
headers.putString("bearer-token", "Some token");
headers.putString("redirect-url", "Some redirect url");
intent.intent.putExtra(Browser.EXTRA_HEADERS, headers);
intent.launchUrl(Activity.this, Uri.parse("http://www.google.com"));
Podemos sempre anexar cabeçalhos da lista de aprovação a solicitações de CORS de guias personalizadas. No entanto, o Chrome filtra os cabeçalhos não aprovados por padrão. Embora outros navegadores possam ter comportamentos diferentes, os desenvolvedores podem esperar que os cabeçalhos não aprovados sejam bloqueados em geral.
A maneira compatível de incluir cabeçalhos não aprovados na lista de guias personalizadas é primeiro verificar a conexão de origem cruzada usando um link de acesso digital. A próxima seção mostra como configurá-los e iniciar uma intent de guias personalizadas com os cabeçalhos necessários.
Como adicionar cabeçalhos extras a intents de guia personalizada
Configurar Digital Asset Links
Para permitir que cabeçalhos não aprovados sejam transmitidos por intents da guia personalizada, é necessário configurar um link de recursos digitais entre o app Android e a Web que verifique se o autor é proprietário dos dois aplicativos.
Siga o guia oficial para configurar um Digital Asset Link. Para a relação de link, use "delegate_permission/common.use_as_origin", que indica que os dois aplicativos pertencem à mesma origem depois que o link é verificado.
Criar um intent de guia personalizada com cabeçalhos extras
Há várias maneiras de criar uma intent de guias personalizadas. Você pode usar o builder disponível no AndroidX adicionando a biblioteca às dependências de build:
MULTI_LINE_CODE_PLACEHOLDER_1
Crie a intent e adicione mais cabeçalhos:
MULTI_LINE_CODE_PLACEHOLDER_2
Configure uma conexão de guias personalizadas para validar o link do recurso
Uma conexão de guias personalizadas é usada para configurar um CustomTabsSession
entre o app e a
guia do Chrome. É preciso fazer a sessão para verificar se o app e o app da Web pertencem à mesma origem.
A verificação só vai ser aprovada se os Digital Asset Links tiverem sido configurados corretamente.
É recomendável chamar CustomTabsClient.warmup()
. Ele permite que o app do navegador seja pré-inicializado em segundo plano e acelere o processo de abertura do URL.
MULTI_LINE_CODE_PLACEHOLDER_3
Configurar um callback que inicie a intent após a validação
A CustomTabsCallback
foi transmitida para a sessão. Configuramos o
onRelationshipValidationResult()
para iniciar a CustomTabsIntent
criada
anteriormente quando a verificação de origem é bem-sucedida.
MULTI_LINE_CODE_PLACEHOLDER_4
Vincular a conexão do serviço de guias personalizadas
A vinculação do serviço inicia o serviço e o onCustomTabsServiceConnected()
da conexão
será chamado. Não se esqueça de desvincular o serviço corretamente. Normalmente, a vinculação e a desvinculação
são feitas nos métodos onStart()
e onStop()
do ciclo de vida da atividade.
// Bind the custom tabs service connection.
// Call this in onStart()
CustomTabsClient.bindCustomTabsService(this,
CustomTabsClient.getPackageName(MainActivity.this, null), connection);
// …
// Unbind the custom tabs service.
// Call this in onStop().
unbindService(connection);
Código do aplicativo de demonstração
Veja mais detalhes sobre o serviço de guias personalizadas aqui. Consulte o repositório do GitHub android-browser-helper para conferir um app de exemplo funcional.
Resumo
Neste guia, mostramos como adicionar cabeçalhos arbitrários às solicitações de CORS de guias personalizadas. Os cabeçalhos listados podem ser anexados a cada solicitação de CORS de guias personalizadas. Geralmente, os cabeçalhos não aprovados são considerados não seguros nas solicitações de CORS e são filtrados pelo Chrome por padrão. Anexá-los só é permitido para clientes e servidores da mesma origem, verificados por um Digital Asset Link.