Agrega encabezados de solicitud HTTP adicionales

Las solicitudes HTTP contienen encabezados como User-Agent o Content-Type. Además de los encabezados que adjuntan los navegadores, las apps para Android pueden agregar encabezados adicionales, como Cookie o Referrer, a través del intent adicional EXTRA_HEADERS. Por motivos de seguridad, Chrome filtra algunos de los encabezados adicionales según cómo y dónde se inicia un intent.

Las solicitudes entre orígenes requieren una capa adicional de seguridad, ya que el cliente y el servidor no pertenecen a la misma parte. En esta guía, se explica cómo iniciar esas solicitudes a través de las pestañas personalizadas de Chrome, es decir, los intents que se inician desde apps que abren una URL en la pestaña del navegador. Hasta Chrome 83, los desarrolladores podían agregar cualquier encabezado cuando iniciaban una pestaña personalizada. A partir de la versión 83, Chrome comenzó a filtrar todos los encabezados de origen cruzado, excepto los que se encuentran en la lista de entidades aprobadas, ya que los que no se encuentran en la lista representaban un riesgo de seguridad. A partir de Chrome 86, es posible adjuntar encabezados que no están en la lista de entidades aprobadas a las solicitudes entre orígenes cuando el servidor y el cliente están relacionados mediante un vínculo de recursos digitales. Este comportamiento se resume en la siguiente tabla:

Versión de Chrome Encabezados de CORS permitidos
antes de Chrome 83 aprobadas, no aprobadas
De Chrome 83 a Chrome 85 incluida en la lista de entidades permitidas
a partir de Chrome 86 aprobada o no aprobada cuando se configura un vínculo de recursos digitales

Tabla 1: Filtrado de encabezados de CORS que no están en la lista de entidades aprobadas

En este artículo, se muestra cómo configurar una conexión verificada entre el servidor y el cliente y usarla para enviar encabezados HTTP de listas de entidades aprobadas y no aprobadas. Puedes ir a Cómo agregar encabezados adicionales a los intents de pestañas personalizadas para ver el código.

Segundo plano

Encabezados de solicitud de CORS en la lista de entidades aprobadas y no aprobadas

El uso compartido de recursos multiorigen (CORS) permite que una aplicación web de un origen solicite recursos de un origen diferente. La lista de encabezados aprobados por CORS se mantiene en el Estándar HTML. En la siguiente tabla, se muestran ejemplos de encabezados de la lista de entidades aprobadas:

Encabezado Descripción
accept-language Anuncia los lenguajes naturales que comprende el cliente.
content-language describe el lenguaje destinado al público actual
content-type Indica el tipo de contenido multimedia del recurso.

Tabla 2: Ejemplo de encabezados de CORS aprobados.

Los encabezados de la lista de entidades aprobadas se consideran seguros porque no contienen información sensible del usuario y es poco probable que hagan que el servidor realice operaciones potencialmente dañinas.

En la siguiente tabla, se muestran ejemplos de encabezados que no están en la lista de entidades aprobadas:

Encabezado Descripción
bearer-token autentica al cliente en un servidor
origin Indica el origen de la solicitud.
galleta contiene cookies configuradas por el servidor

Tabla 3: Ejemplos de encabezados de CORS que no están en la lista de entidades aprobadas.

El estándar HTML desaconseja adjuntar encabezados que no estén en la lista de entidades aprobadas a las solicitudes de CORS, y los servidores suponen que las solicitudes entre dominios solo contienen encabezados que están en la lista de entidades aprobadas. El envío de encabezados que no están en la lista de entidades aprobadas desde dominios de origen cruzado permitiría que las apps de terceros maliciosas creen encabezados que usen de forma inadecuada las cookies del usuario que Chrome (o cualquier otro navegador) almacena y adjunta a las solicitudes. Las cookies podrían autenticar transacciones de servidores maliciosas que, de otro modo, no serían posibles.

Cómo adjuntar encabezados de la lista de entidades aprobadas de CORS a las solicitudes de pestañas personalizadas

Las pestañas personalizadas son una forma especial de iniciar páginas web en una pestaña del navegador personalizada. Los intents de pestaña personalizada se pueden crear con CustomTabsIntent.Builder(). También puedes adjuntar encabezados a estos intents con un Bundle con la marca 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"));

Siempre podemos adjuntar encabezados de la lista de entidades aprobadas a las solicitudes de CORS de las pestañas personalizadas. Sin embargo, Chrome filtra los encabezados que no están en la lista de entidades aprobadas de forma predeterminada. Si bien es posible que otros navegadores tengan un comportamiento diferente, los desarrolladores deben esperar que los encabezados que no estén en la lista de entidades aprobadas se bloqueen en general.

La forma admitida de incluir encabezados que no están en la lista de entidades aprobadas en las pestañas personalizadas es verificar primero la conexión entre orígenes con un vínculo de acceso digital. En la siguiente sección, se muestra cómo configurarlos y cómo iniciar un intent de pestañas personalizadas con los encabezados necesarios.

Agrega encabezados adicionales a los intents de pestañas personalizadas

Para permitir que los encabezados que no están en la lista de entidades aprobadas se pasen a través de los intents de la pestaña personalizada, es necesario configurar un vínculo de recursos digitales entre la aplicación para Android y la aplicación web que verifique que el autor es propietario de ambas aplicaciones.

Sigue la guía oficial para configurar una vinculación de recursos digitales. Para la relación de vínculo, usa "delegate_permission/common.use_as_origin", que indica que ambas apps pertenecen al mismo origen una vez que se verifica el vínculo.

Crea un intent de pestaña personalizada con encabezados adicionales

Existen varias formas de crear un intent de pestañas personalizadas. Para usar el compilador disponible en AndroidX, agrega la biblioteca a las dependencias de compilación:

MULTI_LINE_CODE_PLACEHOLDER_1

Compila el intent y agrega encabezados adicionales:

MULTI_LINE_CODE_PLACEHOLDER_2

Se usa una conexión de pestañas personalizadas para configurar un CustomTabsSession entre la app y la pestaña de Chrome. Necesitamos la sesión para verificar que la app y la app web pertenezcan al mismo origen. La verificación solo se aprobará si los vínculos de recursos digitales se configuraron correctamente.

Se recomienda llamar a CustomTabsClient.warmup(). Permite que la aplicación del navegador se inicialice previamente en segundo plano y acelere el proceso de apertura de la URL.

MULTI_LINE_CODE_PLACEHOLDER_3

Cómo configurar una devolución de llamada que inicie el intent después de la validación

Se pasó CustomTabsCallback a la sesión. Configuramos su onRelationshipValidationResult() para que inicie el CustomTabsIntent creado anteriormente una vez que la verificación de origen se realice correctamente.

MULTI_LINE_CODE_PLACEHOLDER_4

Vincula la conexión del servicio de pestañas personalizadas

La vinculación del servicio lo inicia y, con el tiempo, se llamará a onCustomTabsServiceConnected() de la conexión. No olvides desvincular el servicio de forma adecuada. La vinculación y desvinculación suele realizarse en los métodos del ciclo de vida de la actividad onStart() y onStop().

// 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 de la aplicación de demostración

Puedes encontrar más detalles sobre el servicio de pestañas personalizadas aquí. Consulta el repositorio de GitHub de android-browser-helper para ver una app de ejemplo funcional.

Resumen

En esta guía, se muestra cómo agregar encabezados arbitrarios a las solicitudes de CORS de las pestañas personalizadas. Los encabezados de la lista de entidades seguras se pueden adjuntar a cada solicitud de CORS de las pestañas personalizadas. Por lo general, los encabezados que no están en la lista de entidades aprobadas se consideran no seguros en las solicitudes de CORS, y Chrome los filtra de forma predeterminada. Solo se permite adjuntarlos a clientes y servidores del mismo origen, verificados por un vínculo de activos digitales.