Importar archivos de Amazon S3 de forma segura en navegadores
¿Alguna vez te has preguntado cómo importar archivos de forma segura directamente en tu navegador desde Amazon S3? En este DevTip mostramos cómo aprovechar herramientas modernas, en concreto el AWS SDK for JavaScript v3, para obtener archivos sin sobrecargar tu backend, manteniendo las credenciales seguras y garantizando una experiencia de usuario óptima.
¿Por qué importar directamente desde Amazon S3 en el navegador?
Importar archivos directamente desde Amazon S3 en el navegador reduce la carga del servidor y minimiza la sobrecarga de infraestructura. Al trasladar las operaciones de recuperación de archivos al lado del cliente, puedes mejorar el rendimiento de la aplicación. Sin embargo, este enfoque exige prestar especial atención a la seguridad, la autenticación y las configuraciones de rendimiento.
Configurar tu bucket de S3
-
Crea o selecciona un bucket en tu cuenta de AWS.
-
Configura CORS para permitir el acceso desde el navegador. Por ejemplo:
[ { "AllowedOrigins": ["https://my-app.com"], "AllowedMethods": ["GET"], "MaxAgeSeconds": 3000, "AllowedHeaders": ["*"], "ExposeHeaders": ["ETag"] } ] -
Configura un Amazon Cognito Identity Pool vinculado a tu grupo de usuarios y a un rol de IAM autenticado. Desactiva las identidades no autenticadas cuando los archivos requieran un usuario con sesión iniciada.
-
Configura políticas de bucket estrictas y roles de IAM con privilegios mínimos para garantizar que solo se permitan las acciones necesarias.
Usar el AWS SDK for JavaScript
El AWS SDK for JavaScript v3 ofrece un enfoque modular para crear soluciones escalables de
importación de archivos en el navegador. El ejemplo siguiente muestra cómo obtener archivos de S3 de
forma segura usando Amazon Cognito para las credenciales temporales. Instala @aws-sdk/client-s3 y @aws-sdk/credential-providers
en su versión 3 dentro de tu aplicación de navegador empaquetada. Obtén idToken del flujo de inicio de
sesión que ya usas con tu grupo de usuarios y pásalo a createS3Client. Sustituye la región, el ID del
Identity Pool y el nombre del proveedor de inicio de sesión por los de tu configuración; renueva el
token mediante ese flujo de inicio de sesión cuando sea necesario.
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3'
import { fromCognitoIdentityPool } from '@aws-sdk/credential-providers'
function createS3Client(idToken) {
return new S3Client({
region: 'YOUR_REGION',
credentials: fromCognitoIdentityPool({
clientConfig: { region: 'YOUR_REGION' },
identityPoolId: 'YOUR_IDENTITY_POOL_ID',
logins: {
'cognito-idp.YOUR_REGION.amazonaws.com/YOUR_USER_POOL_ID': idToken,
},
}),
})
}
async function fetchFileFromS3(s3Client, bucketName, fileKey) {
const response = await s3Client.send(new GetObjectCommand({
Bucket: bucketName,
Key: fileKey,
}))
if (!response.Body) {
throw new Error('The object response has no body')
}
return response.Body.transformToByteArray()
}
El array de bytes devuelto contiene el objeto completo en la memoria del navegador. Usa esta función auxiliar para archivos de tamaño acotado; no es una descarga por streaming a disco. Captura los fallos en tu interfaz y muestra un error saneado.
Consejos para optimizar el rendimiento
Para mejorar aún más el rendimiento, ten en cuenta estas estrategias:
- Transmite por streaming las descargas grandes hacia un destino adecuado en lugar de construir un array de bytes completo, o usa una URL de descarga prefirmada de corta duración con la gestión de descargas normal del navegador.
- Limita las descargas simultáneas para controlar el ancho de banda y el uso de memoria.
- Reutiliza el cliente del SDK para que su proveedor de credenciales pueda almacenar en caché y renovar las credenciales temporales.
- Implementa estrategias de reintento para gestionar con elegancia los problemas de red transitorios.
- Monitorea el progreso de la descarga cuando consumas un stream de respuesta para ofrecer información clara al usuario.
Prácticas recomendadas de seguridad
Proteger las importaciones desde el navegador es fundamental. Sigue estas pautas:
-
Usa los Amazon Cognito Identity Pools para evitar distribuir claves de acceso permanentes de AWS. Las credenciales temporales siguen siendo visibles para quien usa el navegador, por lo que sus permisos deben tener un alcance muy restringido.
-
Configura roles de IAM con privilegios mínimos y aplica políticas de bucket estrictas. Por ejemplo, una política de IAM mínima podría verse así:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::your-bucket/*" } ] } -
Exige únicamente endpoints HTTPS, para garantizar que todas las comunicaciones sean seguras.
-
Configura CORS para orígenes de navegador de confianza. CORS no es autorización y no restringe a los clientes que no son navegadores; el acceso lo aplican IAM y las políticas de bucket.
AllowedHeaders: ["*"]admite los encabezados de firma y de sesión del SDK sin conceder permisos adicionales sobre los objetos. -
Rota las credenciales con regularidad y revisa las políticas de IAM para mantener una buena higiene de seguridad.
Problemas comunes y soluciones
- Errores de CORS: verifica que la configuración de CORS de tu bucket de S3 incluya correctamente el dominio de tu aplicación.
- Problemas con las credenciales: revisa con atención la configuración de tu Amazon Cognito Identity Pool y asegúrate de que los roles de IAM estén configurados con acceso de privilegios mínimos.
- Dificultades de rendimiento: limita las descargas simultáneas y evita acumular objetos grandes
en memoria. Los ajustes de subida multiparte no mejoran las descargas de
GetObject. - Limitaciones de tamaño de archivo: usa streaming o las descargas nativas del navegador para los archivos que superen el presupuesto de memoria de tu aplicación.
Conclusión
Implementar importaciones seguras de archivos desde Amazon S3 en el navegador requiere coordinar con cuidado la seguridad, el rendimiento y la experiencia de usuario. Aprovechar el AWS SDK for JavaScript v3 junto con los Amazon Cognito Identity Pools ofrece una solución escalable y robusta. Si prefieres un enfoque gestionado que se encargue de estas complejidades por ti, considera explorar el Robot para importaciones desde S3 de Transloadit.
