Proteger las vistas web con pestañas personalizadas de Chrome

Cuadros a cuadros potencia a los innovadores en el ámbito de la tecnología financiera al proporcionarles acceso a datos financieros a través de una API uniforme. Con el fin de ayudar a los usuarios finales a conectar sus datos bancarios a aplicaciones fintech, Plaid desarrolló Link, un módulo desplegable que maneja la validación de credenciales, la autenticación multifactor y el manejo de errores para cada banco compatible.

Los desarrolladores de Android tenían que abrir URL de enlace en Vistas web. Cada aplicación que quería usar Link requería mucho esfuerzo de desarrollador y, sin estandarización, era probable que hubiera errores en algunas de las implementaciones. Para mejorar la experiencia del desarrollador, recientemente lanzamos un SDK que hace que WebView sea fácil de integrar en cualquier aplicación con unas pocas líneas de código.

Además, las vistas web no son completamente seguras para los usuarios finales que ingresan información confidencial en el flujo de enlaces. Para que nuestro SDK sea lo más seguro posible, lo hemos implementado utilizando pestañas personalizadas de Chrome en lugar de las vistas web de Android. En este artículo explicamos por qué hemos tomado esa decisión y cómo hemos superado los problemas técnicos que encontramos en el camino.

Evaluando Nuestras opciones

Como SDK, nuestro código se ejecuta en las aplicaciones de otros desarrolladores y, a su vez, en sus procesos de aplicación. Para ejecutar la aplicación web de enlace en una vista web, Javascript debe estar habilitado. Esto abre la puerta a que otras aplicaciones ejecuten código malicioso, como registrar devoluciones de llamada que intentan interceptar nombres de usuario y contraseñas. Además, una aplicación maliciosa podría abrir otra página web que imite el flujo de enlaces en un intento de phishing.

Al buscar una solución fácil de integrar para los desarrolladores, intuitiva para los usuarios finales y segura, evaluamos varias opciones:

  1. crear un flujo de enlaces nativo: Debido a que los flujos de enlaces nativos también se ejecutarían en el proceso de otra aplicación, los desarrolladores expertos podrían usar la reflexión para encontrar nuestros textos de edición de entrada y registrar devoluciones de llamada de una manera similar a Javascript en una vista web.

  2. creación de una aplicación de autenticación independiente: Esto proporcionaría una experiencia de espacio aislado nativa y sería una experiencia ideal para los usuarios finales; sin embargo, muchos usuarios no querrían descargar una aplicación adicional de Play Store. Esto significa que necesitaríamos una solución alternativa para los usuarios que se nieguen a descargar la aplicación.

  3. abrir enlace en una ventana de navegador separada: Esta sería una solución segura y aislada. Casi todos los usuarios tienen instalado un navegador, pero el cambio de contexto de una aplicación a un navegador introduciría un retraso notable, especialmente en dispositivos de gama baja.

  4. uso de Pestañas Personalizadas de Chrome: Esta es la solución que elegimos, ya que no tenía ninguno de los inconvenientes mencionados anteriormente.

Nuestra elección: Pestañas personalizadas de Chrome

Las pestañas personalizadas de Chrome (CCT) son una parte del navegador Chrome que se integra con el marco de trabajo de Android para permitir que las aplicaciones abran sitios web en un proceso ligero. CCT se abre más rápido que un navegador y, si está precargado a través de su llamada de calentamiento, es potencialmente incluso más rápido que una vista web. Aunque todavía ejecuta Javascript, está en su propio proceso, lo que evita que las aplicaciones ejecuten código malicioso. Además, la interfaz de usuario CCT proporciona una barra de acciones que muestra la URL de la página que se está cargando, junto con un icono de candado de verificación SSL para páginas seguras. Esto asegura a los usuarios que se muestra la página correcta.

alt

Si bien no todos los usuarios tienen instalado Chrome, la gran mayoría lo tiene. Para aquellos que no lo hacen, estamos utilizando el método de reserva del navegador descrito anteriormente (opción 3); aparte de agregar una línea de código, obtenemos la reserva de forma gratuita desde CCT. Como se señaló anteriormente, el respaldo del navegador no es la experiencia de usuario ideal debido a su latencia, pero mantiene el alto nivel de seguridad que requiere Plaid.

A medida que desarrollamos la solución CCT, nos topamos con varias complicaciones y las abordamos:

  • Obtención de datos de eventos

  • Recuperar el resultado final

  • Control del proceso de actividad de CCT &

Obtención de datos de eventos

Cuando un usuario navega entre pantallas en Link, se produce una redirección y los datos se proporcionan a los desarrolladores en los parámetros de URL.

alt

Esta información de redirección es valiosa para los desarrolladores, ya que les ayuda a comprender el comportamiento del usuario. Con CCT ejecutándose en su propio proceso y sin proporcionar una devolución de llamada de redirección, esta información normalmente sería inaccesible, lo que haría que nuestro SDK seguro fuera menos funcional para los desarrolladores que sus implementaciones personalizadas de WebView.

Para proporcionar esta información desde CCT, registramos los eventos de redirección en el servidor en un almacén de datos Redis. Cuando el SDK abre Link, realiza una llamada de arranque a nuestros servidores, que proporcionan un ID de canal por usuario elegido por nosotros y una clave secreta. A continuación, el SDK crea un objeto de trabajo con ámbito de aplicación, que sondea el servidor mediante una secuencia de intervalos RX. En cada llamada de sondeo, proporcionamos al servidor el ID de canal, la clave secreta y el UUID del último evento (o null) para obtener los últimos eventos.

1
2
3
4
5
6
7
8
9
10
11
12

Observable.intervalo (intervalo, Unidad de tiempo.SEGUNDOS)
.subscribeOn (Planificadores.cálculo())
.observeOn (AndroidSchedulers.Hilo principal())
.Un solo plano (llamada de trabajo de Makenet())
.suscribirse(
{
// Manejar los mensajes
},
{
// el manejo de errores
})

El Android framework puede matar cualquier proceso, incluyendo la aplicación a través de la tela Escocesa del SDK. Dado que el objeto worker está vinculado a la aplicación, esto provocaría que el worker se detuviera. Si el usuario continuaba el flujo (con éxito o sin éxito), el SDK haría una llamada final al canal y obtendría los eventos restantes. Los eventos solo se perderían si el usuario abortaba el flujo y forzaba la aplicación.

Recuperar el resultado final

De forma similar a pasar datos de eventos a los clientes, Link utiliza la URL para indicar que el usuario ha completado el flujo. La URL correspondiente incluye los datos necesarios, como la clave pública o un código de error.

Dado que no podemos acceder a la URL con CCT, almacenamos el resultado final en Redis con el mismo ID de canal. Si bien esto significa que nuestro trabajador de votación sabría cuando Link haya terminado, no habría garantía de que el trabajador aún estaría vivo. Incluso si estuviera vivo, el usuario puede tener que esperar hasta la siguiente llamada de sondeo para que se entregue el resultado, lo que podría ser un par de segundos largos.

Para garantizar que el resultado se entrega a tiempo, utilizamos un enlace profundo para volver a abrir el SDK. El enlace profundo se construye utilizando el ID de aplicación de la aplicación, que debe estar asociado con el secreto del cliente y en la lista blanca del panel de desarrolladores. Esto, además del hecho de que solo una aplicación en un dispositivo puede tener el mismo ID de aplicación, garantiza que ninguna otra aplicación intercepte la redirección. A continuación, la aplicación web de enlaces crea un URI de intent, que se activa al final del flujo de enlaces.

1
2

intención://redirect/#Intención;scheme=a cuadros;paquete=$nombrepaquete;end;

Nuestro SDK incluye un filtro práctico para manejar la URI, de modo que la aplicación de re-abre y hace una llamada directamente a la canal inmediatamente.

1
2
3
4
5
6
7
8
9
10
11

<intent-filter>
<action android:name="android.intención.acto.VER" />
<category android:name="android.intención.categoría.PREDETERMINADO" />
<categoría android: name = " android.intención.categoría.NAVEGABLE" />
<datos
android:host="redirect"
android:esquema = "a cuadros"" />
</ filtro de intención>

Control de CCT

CCT carece de interfaces para que la aplicación:

  • escuchar cuándo el usuario cierra la actividad

  • detectar cuando el usuario ha hecho clic en la opción «Abrir en el navegador»

  • forzarlo a cerrar

Hemos trabajado con éxito en torno a todas estas deficiencias.

Primero, para escuchar cuando el usuario cierra la actividad, abrimos CCT usando startActivityForResult y le pasamos un código de solicitud. Si el usuario cierra CCT usando la X en la esquina superior izquierda del botón atrás del sistema, la devolución de llamada onActivityResult se activa con el código de solicitud que proporcionamos y un código de resultado de Actividad.RESULT_CANCELED. La intención de datos no incluye ninguna información, pero podemos hacer una llamada final al canal para obtener los eventos restantes. Luego los pasamos a la aplicación cliente y devolvemos un objeto LinkCancellation, indicando que el enlace fue cerrado intencionalmente por el usuario.

A continuación, la preocupación potencial de detectar cuando el usuario ha hecho clic en «Abrir en el navegador» es que el usuario podría pasar por todo el flujo en una aplicación separada, a saber, el navegador. Esto no es un problema para nosotros, porque los sistemas de sondeo e intención siguen funcionando de la misma manera y aún podemos obtener los datos necesarios.

Finalmente, cuando el usuario complete el flujo con éxito y se active la intent de resultado, el proceso CCT permanecerá abierto y en la lista de tareas del usuario. Este proceso fantasma no solo sería un desperdicio, sino que también podría ser confuso para un usuario cuando presiona el botón del sistema «tareas recientes». Por lo tanto, necesitamos una forma de forzar el cierre de CCT cuando se complete el flujo.

Para hacer esto, utilizamos el patrón que se muestra en la biblioteca OpenID AppAuth para Android. En lugar de manejar el resultado en la actividad que abre el enlace, colocamos el filtro de intents en una actividad separada. Esta segunda actividad maneja todas las redirecciones desde la aplicación web, que incluyen: terminaciones exitosas, errores que cierran el flujo, redirecciones de OAuth o de aplicación a aplicación y errores generales del sistema. A continuación, la actividad devuelve los datos a la actividad de apertura utilizando una intent con la Intent.FLAG_ACTIVITY_SINGLE_TOP e Intent.FLAG_ACTIVITY_CLEAR_TOP flags. Si se usan juntos, borran todo lo que hay en la pila por encima de la actividad de apertura, incluido el CCT.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

val intención = Intent(actividad, LinkActivity::de la clase.java)
cuando (state) {
es RedirectState.ChromeCustomTabsComplete -> {
intención.putExtra (LINK_CHROME_CUSTOM_TABS_COMPLETE_REDIRECT, true)
intent.putExtra(LINK_RESULT_CODE, state.resultCode)
intent.putExtra(LINK_RESULT, state.result)
}
is RedirectState.UserInitiatedChromeCustomTabsViewClose -> {
intent.putExtra(LINK_CHROME_CUSTOM_TABS_USER_CLOSE_REDIRECT, true)
}
is RedirectState.OAuth -> {
intent.putExtra(LINK_OAUTH_REDIRECT, true)
intent.putExtra(LINK_OAUTH_STATE_ID, state.oauthStateId)
}
is RedirectState.RedirectError ->
intent.putExtra (ERROR LINK_REDIRECT_ERROR, verdadero)
}
intención.flags = Intención.FLAG_ACTIVITY_SINGLE_TOP o Intent.FLAG_ACTIVITY_CLEAR_TOP
intención de devolución

alt

Reflexiones finales sobre CCT

Con el fin de proporcionar una experiencia segura en un espacio aislado que no está disponible en vistas web o flujos nativos, CCT es una solución viable. Es fácil de integrar para los desarrolladores y proporciona una mejor experiencia de usuario que abrir ventanas de navegador gracias a su naturaleza ligera y velocidad.

La naturaleza de caja de arena de CCT y la API limitada significan que no está exenta de inconvenientes. Escuchar los redireccionamientos de URL, obtener los resultados finales y controlar el proceso de CCT nos requirió encontrar soluciones creativas. Estas soluciones se basaban en la comprensión de las funciones integradas de Android, especialmente el marco de intent.

Los beneficios para desarrolladores y consumidores bien merecieron el esfuerzo requerido y recomendamos usar CCT en otras aplicaciones y SDK para una integración rápida y segura. Además, puede utilizar los consejos que se proporcionan aquí para mejorar la experiencia del usuario (y del desarrollador).

Si está interesado en resolver problemas únicos que serán utilizados por miles de desarrolladores y millones de consumidores, visite nuestra página de empleo.

You might also like

Deja una respuesta

Tu dirección de correo electrónico no será publicada.