Primeros pasos con la seguridad de React Native
Kingsley Ubah
7 de abril de 2022
0 minutos de lecturaReact ofrece una forma sencilla e intuitiva de crear interfaces de usuario interactivas. Te permite crear aplicaciones complejas a partir de pequeñas piezas de código independientes llamadas componentes. React Native es una extensión de React que permite a los desarrolladores combinar técnicas de tecnologías web como JavaScript con React para crear aplicaciones móviles multiplataforma.
Esto permite a los desarrolladores escribir código una sola vez para varias plataformas, lo que acelera el desarrollo. React Native usa un DOM virtual para ejecutar los componentes y el código de las aplicaciones en dispositivos con Android, Android TV, iOS, macOS, tvOS, web, Windows y UWP.
Este nivel de adopción es excelente para React, ya que la tecnología móvil crece y evoluciona a una velocidad sin precedentes. Para 2025, se estima que habrá 7.49 mil millones de usuarios móviles en todo el mundo. Las aplicaciones móviles ya son omnipresentes y cada vez son más sofisticadas para compartir, manejar y proteger los datos de los usuarios.
Como desarrollador de una aplicación centrada en los usuarios, eres responsable de proteger la información de quienes la usan y de mantener segura la información confidencial del servidor. Por eso, debes tomar medidas para garantizar que cada persona solo vea aquello a lo que tiene autorización para acceder y que la información de los usuarios almacenada en la base de datos esté protegida.
Para ayudar a proteger la información de los usuarios finales, es indispensable que las aplicaciones no expongan claves privadas, información de bases de datos, archivos confidenciales ni partes de la página que muestren la estructura o las operaciones del back end. Exploremos algunos desafíos de seguridad que enfrentan los desarrolladores de React Native al crear aplicaciones móviles, como la transferencia segura de datos, los protocolos de autenticación y las vulnerabilidades en las dependencias. También veremos cómo resolver cada desafío.
Transferencia segura de datos
Es difícil pensar en una aplicación móvil que no necesite datos de un servidor remoto. De forma predeterminada, React Native solo usa HTTPS para las llamadas a la API y las transferencias de datos.
Aunque hay formas de anular esta configuración predeterminada, usar un protocolo que no sea HTTPS causará problemas con el proveedor al publicar la aplicación en la tienda de aplicaciones. Y lo que es más grave, puede exponer tu aplicación móvil a distintos tipos de filtraciones de datos.
Puedes fijar manualmente en una aplicación móvil los certificados de confianza del host remoto para prevenir ataques de intermediario (MITM) y aumentar la seguridad de la aplicación. Hay varias bibliotecas de código abierto de React Native adecuadas para fijar certificados, como react-native-ssl-pinning de MaxToyberman o react-native-cert-pinner de Approov.
Fijar certificados con la biblioteca React Native SSL pinning
React Native SSL pinning convierte los certificados en archivos .cer que puedes agregar como recursos al paquete de tu aplicación móvil, igual que agregarías una imagen o una fuente personalizada.
La herramienta ofrece un reemplazo de fetch que podemos usar para realizar solicitudes HTTP.
Para fijar un certificado, usa este código:
Para fijar una clave pública, usa este código:
La biblioteca usa dos módulos nativos internamente: AFNetworking para iOS y okhttp3 para Android. El módulo AFNetworking usa automáticamente los archivos .cer en los recursos. OkHttp3 usa la propiedad JavaScript sslPinning para asociarla con .cer.
Fijar certificados con react-native-cert-pinner
react-native-cert-pinner es otra biblioteca que permite fijar certificados en tu aplicación móvil. Las fijaciones pueden ser el hash SHA256 en Base64 de la clave pública del certificado o el hash SHA1 en Base64 del certificado.
La biblioteca ofrece una utilidad, pinset, que genera un archivo info.plist para iOS o un archivo GeneratedCertificatePinner.java para Android. Luego, el código nativo se vincula con este archivo.
Internamente, la biblioteca usa TrustKit en iOS y okhttp3 en Android.
Para fijar certificados con react-native-cert-pinner, primero genera una configuración inicial con este comando:
Después de inicializarla, determina qué URL quieres fijar y el hash de la clave pública de cada certificado.
Luego, ingresa los hashes de las claves públicas que quieras para tu dominio en el archivo pinset.json:
Nota: Los dominios que comienzan con un asterisco (*) incluyen todos los subdominios.
Ahora, genera los archivos de origen del proyecto nativo con el siguiente comando:
Esta acción debería generar los archivos correspondientes:
Recomendamos usar una biblioteca que permita fijar la clave pública del certificado, ya que una fijación creada a partir de un certificado dejará de funcionar cuando este venza. Ambas bibliotecas de esta sección permiten fijar claves públicas.
Por lo general, se recomienda fijar certificados en una aplicación móvil solo cuando quieres tener bastante certeza de la identidad de un host remoto.
Protocolos de autenticación
La autenticación ayuda a establecer confianza al identificar al usuario o sistema específico que está detrás de una solicitud de red. Esta identificación permite que el servidor determine si debe permitir que el usuario acceda a un recurso determinado.
La mayoría de las aplicaciones móviles deben mostrar algún tipo de datos personalizados al usuario. Por ejemplo, el perfil de Facebook o la lista de contactos de WhatsApp. El sistema de autenticación ayuda al servidor a identificar al usuario para entregarle los datos correspondientes en estas aplicaciones.
Una forma común de configurar la autenticación de usuarios en React Native es crear distintos grupos de pantallas. Los desarrolladores suelen hacerlo con una biblioteca de enrutamiento como Stack Navigator.
Un grupo administra las pantallas que podrían ver los usuarios no autenticados. Estas pueden incluir las pantallas de inicio de sesión, registro y restablecimiento de contraseña. La aplicación usa estas pantallas para autenticar al usuario.
Un segundo grupo es para los usuarios autenticados. Esta pila incluye el panel, la configuración, la cuenta, el feed y cualquier otra pantalla relacionada con el contenido del usuario.
Este código de ejemplo divide las pantallas en dos grupos: AppStack para los usuarios autenticados y AuthStack para los usuarios no autenticados:
Después de crear ambos grupos de pantallas, crea un componente Router que elija qué pila mostrar según el estado de autenticación del usuario.
Luego, usa ambas pilas dentro de NavigationContainer. Un componente de react-navigation envuelve todas las rutas de navegación en React Native.
authData representa los datos que el usuario proporciona en la pantalla de autenticación, por ejemplo, SignInScreen. Este código autentica al usuario:
La función signIn se conecta con la API y actualiza authData según la respuesta. Puedes almacenar allí los datos del perfil del usuario obtenidos de la API. La función signOut borra los datos. En algunos casos, puede conectarse con la API para invalidar un token.
Se necesita un estado de carga porque el proceso de autenticación es asíncrono y toma tiempo. Puedes escuchar este estado para mostrar una animación de carga en la interfaz de usuario (UI) de tu aplicación mientras el servidor procesa la solicitud.
Por último, asegúrate de que todos los componentes puedan acceder a Context envolviéndolo con AuthContext.Provider.
El protocolo OAuth 2.0
Las aplicaciones móviles de React Native suelen usar el protocolo de autenticación OAuth 2.0 para autenticar a los usuarios. OAuth es una opción popular para aplicaciones web y móviles por su estricta seguridad.
Los cuatro participantes de un flujo de OAuth son:
Propietario del recurso: Es dueño de los datos en el servidor de recursos. Por ejemplo, un usuario de Facebook es el propietario del recurso de los datos de su perfil de Facebook.
Aplicación cliente: La aplicación que quiere acceder a estos datos (por ejemplo, la aplicación móvil de Facebook).
Servidor de recursos: La API que almacena los datos a los que la aplicación móvil quiere acceder (por ejemplo, la API de Facebook).
Servidor de autorización: El motor principal de OAuth.
OAuth solicita a los usuarios que se autentiquen mediante un servicio de terceros, como Google, Facebook o GitHub. Una vez que termina el proceso de autenticación, el tercero redirige al usuario a la aplicación con un código de verificación. La aplicación puede intercambiar este código por un JSON Web Token (JWT) o cualquier otro tipo de token.
Estas redirecciones son seguras para las aplicaciones web porque se garantiza que las URL sean únicas en la web. Sin embargo, las aplicaciones móviles no cuentan con un método centralizado para registrar esquemas de URL.
Para abordar este problema de seguridad, debemos agregar una verificación llamada PKCE (se pronuncia “Pixie”), una extensión de la especificación OAuth 2.0. PKCE usa el algoritmo criptográfico de hash SHA 256 para verificar que las solicitudes de autenticación e intercambio de tokens provengan del mismo cliente.
Este enfoque garantiza que solo la aplicación responsable del flujo de autorización pueda intercambiar correctamente el código de verificación por un JWT.
Una forma sencilla de implementar OAuth nativo de manera segura en React Native es usar un paquete como react-native-app-auth. Este funciona como un puente de React Native para los SDK de AppAuth para iOS y AppAuth para Android, que se comunican con proveedores de OAuth 2.0 y OpenID Connect.
El paquete es compatible con PKCE y con muchos proveedores de OpenID y OAuth 2.0, incluidos Google, Okta, GitHub, Coinbase y FusionAuth.
Busca vulnerabilidades en las dependencias
Los desarrolladores no crean aplicaciones nativas completas solo con React Native. A menudo usamos herramientas de terceros para resolver problemas y mejorar nuestra productividad.
Una aplicación contiene varias dependencias de terceros que ayudan a que sea completa y funcional. El problema es que estas dependencias pueden introducir vulnerabilidades en la aplicación, incluso si nuestro propio código es seguro.
Hay varias formas de empezar a usar Snyk para buscar vulnerabilidades en paquetes de código abierto. Veamos un ejemplo con la popular aplicación de arte de código abierto para React Native Eigen.
La primera forma es usar la CLI de Snyk: instala la herramienta de CLI y crea una cuenta gratuita de Snyk. Una vez que hayas creado la cuenta e instalado la herramienta, ejecuta snyk auth para conectar la CLI con tu cuenta.
Clona el repositorio en tu entorno de desarrollo y luego ejecuta snyk test en el directorio raíz del proyecto clonado. Esto analizará el manifiesto de paquetes en la raíz y buscará problemas en las versiones de los paquetes.
Consejo práctico: También puedes ejecutar snyk monitor para recibir alertas sobre cualquier problema que se detecte en el proyecto después del análisis inicial.

En nuestro ejemplo, se detectaron varios problemas potenciales en el manifiesto de paquetes de la aplicación React Native. Una ventaja útil es que puedes investigar las vulnerabilidades detectadas para obtener más información.
Al revisar la lista, Hermes-engine 0.5.1 presenta una vulnerabilidad conocida que puede causar secuencias de comandos entre sitios (XSS). Puedes mitigarla actualizando a una versión posterior a la 0.7.2, que corrige esta vulnerabilidad específica.

Otra opción para analizar proyectos de React Native es analizarlos directamente desde un repositorio conectando tu cuenta de Snyk con el repositorio de código que prefieras. La ventaja es que Snyk puede realizar análisis continuos para detectar problemas en proyectos con varios colaboradores, ya que revisa el proyecto con cada confirmación o fusión.
Para conectar tu repositorio, crea una cuenta de Snyk. Luego, en el panel de Snyk, haz clic en la plataforma donde está almacenado tu código. Si la plataforma que prefieres no aparece en el menú rápido, haz clic en Other y búscala entre las integraciones de plataformas de Snyk.

Sigue los pasos para conectar el repositorio. Luego, en la página de conexión del repositorio, elige el repositorio que quieres analizar.

Haz clic en el botón Add selected repositories y espera a que termine el análisis. Una ventaja muy útil es que puedes ver los elementos analizados y los resultados.

Al igual que con el análisis de la CLI de Snyk, puedes revisar más detalles sobre la vulnerabilidad detectada y generar una corrección automática en el repositorio.

También puedes integrar Snyk en el editor de código que prefieras para analizar automáticamente tus dependencias en busca de vulnerabilidades mientras desarrollas una aplicación. Por ejemplo, la extensión de Snyk para Visual Studio Code identifica posibles vulnerabilidades no solo en el manifiesto del paquete, sino también en las partes del código donde se llama a ese paquete.
Para terminar
A medida que las aplicaciones móviles usan los datos de formas más sofisticadas, es aún más importante proteger eficazmente la información de los usuarios y resguardar a los usuarios finales. Al igual que las aplicaciones web, las aplicaciones de React Native enfrentan los mismos tipos de desafíos de seguridad, como la transferencia segura de datos, los protocolos de autenticación y las vulnerabilidades en las dependencias.
Consulta esta lista de verificación de prácticas recomendadas de seguridad para React para ayudar a tu equipo a encontrar y corregir problemas de seguridad en sus aplicaciones de React.
Empieza con Capture the Flag
Aprende a resolver desafíos de Capture the Flag viendo nuestro taller virtual introductorio a pedido.
Kingsley Ubah es un desarrollador web full stack y redactor técnico con amplia experiencia.



