Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

1K
Vistas
¿Cómo manejar las descargas de archivos con autenticación basada en JWT?

Estoy escribiendo una aplicación web en Angular donde la autenticación es manejada por un token JWT, lo que significa que cada solicitud tiene un encabezado de "Autenticación" con toda la información necesaria.

Esto funciona bien para llamadas REST, pero no entiendo cómo debo manejar los enlaces de descarga para archivos alojados en el backend (los archivos residen en el mismo servidor donde están alojados los servicios web).

No puedo usar enlaces regulares <a href='...'/> ya que no llevarán ningún encabezado y la autenticación fallará. Lo mismo para los diversos encantamientos de window.open(...) .

Algunas soluciones que pensé:

  1. Genere un enlace de descarga no seguro temporal en el servidor
  2. Pase la información de autenticación como un parámetro de URL y maneje manualmente el caso
  3. Obtenga los datos a través de XHR y guarde el archivo del lado del cliente.

Todo lo anterior es menos que satisfactorio.

1 es la solución que estoy usando en este momento. No me gusta por dos razones: primero, no es ideal en cuanto a seguridad, segundo, funciona pero requiere bastante trabajo, especialmente en el servidor: para descargar algo necesito llamar a un servicio que genera un nuevo "random " url, lo almacena en algún lugar (posiblemente en la base de datos) durante un tiempo y lo devuelve al cliente. El cliente obtiene la url y usa window.open o similar con ella. Cuando se solicite, la nueva URL debe verificar si aún es válida y luego devolver los datos.

2 parece al menos tanto trabajo.

3 parece mucho trabajo, incluso usando las bibliotecas disponibles, y muchos problemas potenciales. (Necesitaría proporcionar mi propia barra de estado de descarga, cargar todo el archivo en la memoria y luego pedirle al usuario que guarde el archivo localmente).

Sin embargo, la tarea parece bastante básica, así que me pregunto si hay algo mucho más simple que pueda usar.

No estoy necesariamente buscando una solución "a la manera Angular". Javascript regular estaría bien.

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Esta es una forma de descargarlo en el cliente mediante el atributo de descarga , la API de obtención y URL.createObjectURL . Obtendría el archivo usando su JWT, convertiría la carga útil en un blob, colocaría el blob en una URL de objeto, establecería la fuente de una etiqueta de anclaje en esa URL de objeto y haría clic en esa URL de objeto en javascript.

 let anchor = document.createElement("a"); document.body.appendChild(anchor); let file = 'https://www.example.com/some-file.pdf'; let headers = new Headers(); headers.append('Authorization', 'Bearer MY-TOKEN'); fetch(file, { headers }) .then(response => response.blob()) .then(blobby => { let objectUrl = window.URL.createObjectURL(blobby); anchor.href = objectUrl; anchor.download = 'some-file.pdf'; anchor.click(); window.URL.revokeObjectURL(objectUrl); });

El valor del atributo de download será el nombre final del archivo. Si lo desea, puede extraer un nombre de archivo deseado del encabezado de respuesta de disposición de contenido como se describe en otras respuestas .

over 4 years ago · Santiago Trujillo Denunciar

0

Técnica

Basado en este consejo de Matias Woloski de Auth0, conocido evangelista de JWT, lo resolví generando una solicitud firmada con Hawk .

Citando a Woloski:

La forma de resolver esto es generando una solicitud firmada como lo hace AWS, por ejemplo.

Aquí tienes un ejemplo de esta técnica, utilizada para enlaces de activación.

back-end

Creé una API para firmar mis URL de descarga:

Petición:

 POST /api/sign Content-Type: application/json Authorization: Bearer... {"url": "https://path.to/protected.file"}

Respuesta:

 {"url": "https://path.to/protected.file?bewit=NTUzMDYzZTQ2NDYxNzQwMGFlMDMwMDAwXDE0NTU2MzU5OThcZDBIeEplRHJLVVFRWTY0OWFFZUVEaGpMOWJlVTk2czA0cmN6UU4zZndTOD1c"}

Con una URL firmada, podemos obtener el archivo

Petición:

 GET https://path.to/protected.file?bewit=NTUzMDYzZTQ2NDYxNzQwMGFlMDMwMDAwXDE0NTU2MzU5OThcZDBIeEplRHJLVVFRWTY0OWFFZUVEaGpMOWJlVTk2czA0cmN6UU4zZndTOD1c

Respuesta:

 Content-Type: multipart/mixed; charset="UTF-8" Content-Disposition': attachment; filename=protected.file {BLOB}

interfaz (por jojoyuji )

De esta manera, puede hacerlo todo con un solo clic de usuario:

 function clickedOnDownloadButton() { postToSignWithAuthorizationHeader({ url: 'https://path.to/protected.file' }).then(function(signed) { window.location = signed.url; }); }
over 4 years ago · Santiago Trujillo Denunciar

0

Una alternativa a los enfoques existentes "fetch/createObjectURL" y "download-token" ya mencionados es un Formulario POST estándar que apunta a una nueva ventana . Una vez que el navegador lea el encabezado del archivo adjunto en la respuesta del servidor, cerrará la nueva pestaña y comenzará la descarga. Este mismo enfoque también funciona bien para mostrar un recurso como un PDF en una nueva pestaña.

Esto tiene un mejor soporte para navegadores más antiguos y evita tener que administrar un nuevo tipo de token. Esto también tendrá una mejor compatibilidad a largo plazo que la autenticación básica en la URL, ya que los navegadores eliminarán la compatibilidad con el nombre de usuario/contraseña en la URL .

En el lado del cliente, usamos target="_blank" para evitar la navegación incluso en casos de falla, lo cual es particularmente importante para las SPA (aplicaciones de una sola página).

La principal advertencia es que la validación JWT del lado del servidor debe obtener el token de los datos POST y no del encabezado . Si su marco administra el acceso a los controladores de ruta automáticamente mediante el encabezado de autenticación, es posible que deba marcar su controlador como no autenticado/anónimo para que pueda validar manualmente el JWT para garantizar la autorización adecuada.

El formulario se puede crear dinámicamente y destruir de inmediato para que se limpie correctamente (nota: esto se puede hacer en JS simple, pero JQuery se usa aquí para mayor claridad) -

 function DownloadWithJwtViaFormPost(url, id, token) { var jwtInput = $('<input type="hidden" name="jwtToken">').val(token); var idInput = $('<input type="hidden" name="id">').val(id); $('<form method="post" target="_blank"></form>') .attr("action", url) .append(jwtInput) .append(idInput) .appendTo('body') .submit() .remove(); }

Simplemente agregue cualquier dato adicional que necesite enviar como entradas ocultas y asegúrese de que se agreguen al formulario.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda