Saltar al contenido principal
Versión: 0.78

Seguridad

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

La seguridad suele pasarse por alto al crear aplicaciones. Es cierto que es imposible construir software completamente impenetrable—aún no hemos inventado una cerradura totalmente infranqueable (después de todo, siguen asaltando bóvedas bancarias). Sin embargo, la probabilidad de ser víctima de un ataque malicioso o exponer vulnerabilidades de seguridad es inversamente proporcional al esfuerzo que estés dispuesto a invertir para proteger tu aplicación. ¡Aunque un candado común se puede forzar, sigue siendo mucho más difícil de superar que un simple gancho de armario!

En esta guía, aprenderás mejores prácticas para almacenar información sensible, autenticación, seguridad de red y herramientas que ayudarán a proteger tu aplicación. Esto no es una lista de verificación previa—es un catálogo de opciones donde cada elección aportará mayor protección a tu aplicación y usuarios.

Almacenamiento de información sensible

Nunca almacenes claves de API sensibles en tu código. Cualquier elemento incluido podría ser accesible en texto plano al inspeccionar el paquete de la aplicación. Herramientas como react-native-dotenv y react-native-config son útiles para variables específicas de entorno como endpoints de API, pero no deben confundirse con variables de entorno del lado del servidor, que suelen contener secretos y claves de API.

Si necesitas una clave de API o secreto para acceder a recursos desde tu aplicación, el método más seguro es implementar una capa de orquestación entre tu app y el recurso. Esto podría ser una función serverless (ej. usando AWS Lambda o Google Cloud Functions) que reenvíe solicitudes con la clave o secreto requerido. Los secretos en código del lado del servidor no son accesibles por los consumidores de API como lo serían en tu código cliente.

Para datos de usuario persistentes, elige el tipo de almacenamiento según su sensibilidad. Al usar tu aplicación, surgirá la necesidad de guardar datos en el dispositivo: ya sea para soportar uso offline, reducir solicitudes de red o conservar tokens de acceso entre sesiones evitando reautenticaciones constantes.

Persistentes vs no persistentes — los datos persistentes se escriben en el disco del dispositivo, permitiendo que tu aplicación los lea entre lanzamientos sin solicitudes de red adicionales ni requerir que el usuario los vuelva a ingresar. Pero esto también hace que los datos sean más vulnerables a accesos no autorizados. ¡Los datos no persistentes nunca se escriben en disco, por lo que no hay nada que acceder!

Async Storage

Async Storage es un módulo mantenido por la comunidad para React Native que ofrece un almacén clave-valor asíncrono y sin cifrado. Async Storage no se comparte entre aplicaciones: cada app tiene su propio entorno sandbox sin acceso a datos de otras aplicaciones.

Do use async storage when...Don't use async storage for...
Persisting non-sensitive data across app runsToken storage
Persisting Redux stateSecrets
Persisting GraphQL state
Storing global app-wide variables

Notas para desarrolladores

Async Storage is the React Native equivalent of Local Storage from the web

Almacenamiento seguro

React Native no incluye soluciones nativas para almacenar datos sensibles. Sin embargo, existen alternativas para las plataformas Android e iOS.

iOS - Keychain Services

Keychain Services permite almacenar de forma segura fragmentos pequeños de información sensible. Es ideal para certificados, tokens, contraseñas y cualquier dato que no deba estar en Async Storage.

Android - Preferencias compartidas seguras

Shared Preferences es el equivalente Android para almacenes clave-valor persistentes. Los datos en Shared Preferences no están cifrados por defecto, pero Encrypted Shared Preferences envuelve esta clase cifrando automáticamente claves y valores.

Android - Keystore

El sistema Android Keystore permite almacenar claves criptográficas en un contenedor que dificulta su extracción del dispositivo.

Para utilizar los servicios de Keychain en iOS o las Preferencias Compartidas Seguras en Android, puedes crear tu propio puente o usar una biblioteca que los encapsule y ofrezca una API unificada, bajo tu propio riesgo. Algunas bibliotecas a considerar:

Evita almacenar o exponer información sensible sin intención. Esto puede ocurrir accidentalmente, por ejemplo al guardar datos sensibles de formularios en el estado de redux y persistir todo el árbol de estado en Async Storage. O al enviar tokens de usuario e información personal a servicios de monitoreo como Sentry o Crashlytics.

Autenticación y Enlaces Profundos

Las aplicaciones móviles tienen una vulnerabilidad única inexistente en la web: los enlaces profundos. Un enlace profundo es un método para enviar datos directamente a una aplicación nativa desde fuentes externas. Un enlace profundo tiene el formato app:// donde app es el esquema de tu aplicación y lo que sigue a // puede usarse internamente para manejar la solicitud.

Por ejemplo, si estás desarrollando una app de comercio electrónico, podrías usar app://products/1 para enlazar profundamente y abrir la página de detalles del producto con ID 1. Puedes pensar en ellos como URLs web, pero con una distinción crucial:

Los enlaces profundos no son seguros y nunca debes enviar información sensible a través de ellos.

La razón es que no existe un método centralizado para registrar esquemas de URL. Como desarrollador, puedes usar casi cualquier esquema configurándolo en Xcode para iOS o agregando un intent en Android.

Nada impide que una aplicación maliciosa intercepte tus enlaces profundos registrando el mismo esquema, accediendo así a los datos del enlace. Enviar app://products/1 no es dañino, pero enviar tokens representa un riesgo de seguridad.

Cuando el sistema operativo tiene múltiples aplicaciones para abrir un enlace, Android muestra un diálogo de desambiguación para que el usuario elija. En iOS, sin embargo, el sistema elige automáticamente sin notificar al usuario. Apple abordó parcialmente esto en iOS 11 con un enfoque "primero en llegar", aunque persisten vulnerabilidades detalladas aquí. Los enlaces universales permiten vincular contenido de forma segura en iOS.

OAuth2 y Redirecciones

El protocolo OAuth2 es extremadamente popular actualmente, considerado el más completo y seguro. OpenID Connect también se basa en él. En OAuth2, el usuario se autentica mediante un tercero que, tras confirmación, redirige a la aplicación con un código de verificación intercambiable por un JWT (JSON Web Token), estándar abierto para transmisión segura de información web.

En la web, este paso de redirección es seguro porque las URLs tienen garantía de unicidad. Esto no aplica en apps móviles debido a la falta de registro centralizado de esquemas de URL. Para mitigar este riesgo, se añade una verificación adicional mediante PKCE.

PKCE, pronunciado "Pixy", significa Prueba de Intercambio de Código Clave (Proof of Key Code Exchange) y es una extensión de la especificación OAuth 2. Esto añade una capa adicional de seguridad que verifica que las solicitudes de autenticación e intercambio de tokens provengan del mismo cliente. PKCE utiliza el Algoritmo Criptográfico de Hash SHA 256. SHA 256 crea una "firma" única para cualquier texto o archivo, pero tiene estas características:

  • Siempre tiene la misma longitud independientemente del archivo de entrada

  • Garantiza producir siempre el mismo resultado para la misma entrada

  • Es unidireccional (es decir, no se puede revertir para revelar la entrada original)

Ahora tienes dos valores:

  • code_verifier: cadena aleatoria larga generada por el cliente

  • code_challenge: el SHA 256 del code_verifier

Durante la solicitud inicial /authorize, el cliente también envía el code_challenge para el code_verifier que mantiene en memoria. Tras recibir la respuesta de autorización, el cliente envía el code_verifier utilizado para generar el code_challenge. El IDP (Proveedor de Identidad) calcula entonces el code_challenge, verifica si coincide con el valor enviado en la primera solicitud /authorize, y solo envía el token de acceso si los valores coinciden.

Esto garantiza que solo la aplicación que inició el flujo de autorización podrá intercambiar correctamente el código de verificación por un JWT. Así, incluso si una aplicación maliciosa accede al código de verificación, será inútil por sí solo. Para ver esto en acción, consulta este ejemplo.

Una biblioteca a considerar para OAuth nativo es react-native-app-auth. React-native-app-auth es un SDK para comunicarse con proveedores OAuth2. Envuelve las bibliotecas nativas AppAuth-iOS y AppAuth-Android y puede soportar PKCE.

React-native-app-auth solo puede admitir PKCE si tu Identity Provider lo admite.

OAuth2 con PKCE

Seguridad de Red

Tus APIs siempre deben usar cifrado SSL. El cifrado SSL protege contra la lectura en texto plano de los datos solicitados entre el servidor y el cliente. Sabrás que el endpoint es seguro porque comienza con https:// en lugar de http://.

Fijación SSL (SSL Pinning)

Usar endpoints https aún podría dejar tus datos vulnerables a interceptación. Con https, el cliente solo confiará en el servidor si puede proporcionar un certificado válido firmado por una Autoridad de Certificación confiable preinstalada en el cliente. Un atacante podría aprovechar esto instalando un certificado CA raíz malicioso en el dispositivo del usuario, haciendo que el cliente confíe en todos los certificados firmados por el atacante. Por lo tanto, confiar únicamente en certificados aún podría dejarte vulnerable a un ataque de intermediario (man-in-the-middle).

La fijación SSL (SSL pinning) es una técnica que puede usarse en el lado del cliente para evitar este ataque. Funciona incrustando (o "fijando") una lista de certificados confiables en el cliente durante el desarrollo, de modo que solo se aceptarán solicitudes firmadas con uno de estos certificados, rechazando cualquier certificado autofirmado.

Al implementar SSL pinning, considera la caducidad de los certificados. Los certificados expiran cada 1-2 años y, cuando ocurre, deben actualizarse tanto en la aplicación como en el servidor. Inmediatamente después de actualizar el certificado en el servidor, las apps que incluyan el certificado antiguo dejarán de funcionar.

Resumen

No existe una forma infalible de manejar la seguridad, pero con esfuerzo consciente y diligencia, es posible reducir significativamente la probabilidad de una brecha de seguridad en tu aplicación. Invierte en seguridad de manera proporcional a la sensibilidad de los datos almacenados, la cantidad de usuarios y el daño que un hacker podría causar al acceder a sus cuentas. Y recuerda: es considerablemente más difícil acceder a información que nunca se solicitó en primer lugar.