Agrega encabezados de solicitud HTTP adicionales

Las solicitudes HTTP contienen encabezados, como Usuario-agente o Tipo de contenido. Además de los encabezados que adjuntan los navegadores, las apps para Android pueden agregar encabezados adicionales, como Cookie o Referrer, mediante el intent adicional EXTRA_HEADERS. Por motivos de seguridad, Chrome filtra algunos de los encabezados adicionales según cómo y dónde se inicie un intent.

Las solicitudes de origen cruzado requieren una capa de seguridad adicional, ya que el cliente y el servidor no son propiedad de la misma parte. En esta guía, se explica cómo iniciar estas solicitudes mediante las pestañas personalizadas de Chrome, es decir, intents iniciados desde apps que abren una URL en esa pestaña. Hasta Chrome 83, los desarrolladores podían agregar cualquier encabezado al iniciar una pestaña personalizada. A partir de la versión 83, Chrome comenzó a filtrar todos los encabezados de origen cruzado aprobados, ya que los encabezados no aprobados suponían un riesgo de seguridad. A partir de Chrome 86, es posible adjuntar encabezados no aprobados a solicitudes de origen cruzado cuando el servidor y el cliente se relacionan 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 en lista de aprobación, no aprobado
De Chrome 83 a Chrome 85 en la lista de aprobación
desde Chrome 86 en adelante en la lista de aprobación o no aprobado cuando se configura un vínculo de recursos digitales

Tabla 1: Filtrado de encabezados de CORS no aprobados.

En este artículo, se muestra cómo configurar una conexión verificada entre el servidor y el cliente y cómo usarla para enviar encabezados HTTP aprobados y no aprobados. Puedes pasar a la sección Cómo agregar encabezados adicionales a los intents de pestaña personalizados para el código.

Información general

Encabezados de la solicitud del CORS en la lista de aprobación y no aprobado

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

Encabezado Descripción
idioma-aceptar Promociona lenguajes naturales que el cliente comprende.
idioma del contenido Describe el lenguaje destinado al público actual.
tipo de contenido indica el tipo de medio del recurso

Tabla 2: Ejemplo de encabezados de CORS que figuran en la lista de aprobación.

Los encabezados que están en la lista de aprobación se consideran seguros porque no contienen información sensible del usuario y es poco probable que provoquen que el servidor realice operaciones potencialmente dañinas.

En la siguiente tabla, se muestran ejemplos de encabezados no aprobados:

Encabezado Descripción
token del portador autentica el cliente en un servidor
origin indica el origen de la solicitud
galleta contiene cookies establecidas por el servidor

Tabla 3: Ejemplo de encabezados de CORS no aprobados.

El estándar de HTML desaconseja adjuntar encabezados no aprobados a las solicitudes de CORS, y los servidores suponen que las solicitudes de origen cruzado solo contienen encabezados incluidos en la lista de aprobación. El envío de encabezados no aprobados desde dominios de origen cruzado permitiría que las apps de terceros maliciosas creen encabezados que hagan un uso inadecuado de las cookies del usuario que Chrome (o algún otro navegador) almacena y adjunta a las solicitudes. Las cookies podrían autenticar transacciones de servidor maliciosas que, de otro modo, no serían posibles.

Cómo adjuntar encabezados de la lista de aprobación de CORS a solicitudes de pestañas personalizadas

Las pestañas personalizadas son una forma especial de iniciar páginas web en una pestaña personalizada del navegador. Los intents de pestaña personalizada se pueden crear con CustomTabsIntent.Builder(). También puedes adjuntar encabezados a estos intents mediante 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 incluidos en la lista de aprobación a las pestañas personalizadas de las solicitudes de CORS. Sin embargo, Chrome filtra los encabezados no aprobados de forma predeterminada. Aunque otros navegadores pueden tener un comportamiento diferente, los desarrolladores deben esperar que los encabezados no aprobados se bloqueen en general.

La forma admitida para incluir encabezados no aprobados en las pestañas personalizadas es verificar primero la conexión de origen cruzado mediante un vínculo de acceso digital. En la siguiente sección, se muestra cómo configurarlos e iniciar un intent de pestañas personalizadas con los encabezados requeridos.

Cómo agregar encabezados adicionales a los intents de pestaña personalizados

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

Sigue la guía oficial para configurar un vínculo 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.

Cómo crear un intent de pestaña personalizado 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 elemento CustomTabsSession entre la app y la pestaña de Chrome. Necesitamos la sesión para verificar que la app y la app web pertenecen al mismo origen. La verificación solo se aprueba si los vínculos de recursos digitales se configuraron correctamente.

Te recomendamos que llames 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 objeto CustomTabsIntent ya creado una vez que la verificación del origen se realice de forma correcta.

MULTI_LINE_CODE_PLACEHOLDER_4

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

La vinculación del servicio inicia el servicio y, en última instancia, se llamará al onCustomTabsServiceConnected() de la conexión. No olvides desvincular el servicio de forma adecuada. Por lo general, la vinculación y la desvinculación se realizan 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 android-browser-helper de GitHub para ver una app de ejemplo que funcione.

Resumen

En esta guía, se demostró cómo agregar encabezados arbitrarios a las solicitudes de CORS de pestañas personalizadas. Los encabezados aprobados se pueden adjuntar a cada solicitud de CORS de pestañas personalizadas. Por lo general, los encabezados no aprobados se consideran no seguros en las solicitudes de CORS y Chrome los filtra de forma predeterminada. Solo se permite adjuntarlas a clientes y servidores del mismo origen, verificados mediante un vínculo de recursos digitales.