Política de origen común y CORS: una guía visual





¡Buen dia amigos!



Les presento a su atención la traducción del artículo "CS Visualized: CORS" de Lydia Hallie.



Todo desarrollador ha tenido que lidiar con un error Access to fetched has been blocked by CORS policy. Hay varias formas de resolver rápidamente este problema. Sin embargo, tomemos nuestro tiempo y echemos un vistazo más de cerca a lo que es una política CORS.



A menudo necesitamos mostrar datos que se encuentran en otro lugar. Antes de que podamos hacer esto, el navegador debe enviar una solicitud al servidor para recibir estos datos.



Digamos que queremos obtener información sobre un usuario en nuestro sitio www.mywebsite.comdesde un servidor ubicado en el sitio api.website.com.







¡Excelente! Acabamos de enviar una solicitud al servidor y, a cambio, recibimos datos JSON.



Ahora intentemos enviar una solicitud similar a otro dominio. En lugar de enviar una solicitud con, enviémosla www.mywebsite.comcon www.anotherdomain.com.







¿Que pasó? Enviamos exactamente la misma solicitud, pero esta vez el navegador muestra algún tipo de error.



Estamos viendo CORS en acción. ¿Por qué ocurrió este error y qué significa?



Política de origen común



Hay algo en la web llamado Política de origen genérico (en lo sucesivo, POP). De forma predeterminada, solo tenemos acceso a aquellos recursos que están en el mismo origen que el origen de nuestra solicitud. Por ejemplo, podemos cargar una imagen ubicada en https://mywebsite.com/image1.png.



Una fuente es diferente cuando está ubicada en un (sub) dominio, protocolo o puerto diferente.







Genial, pero ¿por qué necesitas POP?



Digamos que no existe, y accidentalmente haces clic en un enlace viral que tu tía publicó en Facebook. Este enlace lo redirige a un "sitio malicioso" que tiene un iframe incrustado que carga el sitio de su banco e inicia sesión correctamente mediante una cookie.



Los desarrolladores del "sitio malvado" se aseguraron de que tuviera acceso al iframe y pudieran interactuar con el contenido del DOM del sitio de su banco para transferir fondos a su cuenta en su nombre.







Sí ... este es un problema de seguridad serio. No queremos que nadie tenga acceso a nada sin nuestro conocimiento.



Afortunadamente, EPP existe. Esta política restringe el acceso a recursos de otras fuentes.







En este caso, la fuente está www.evilwebsite.comintentando acceder al recurso desde la fuente www.bank.com. EPP bloquea este acceso y prohíbe que los desarrolladores de sitios maliciosos accedan a sus datos bancarios.



Vale, pero ... ¿cómo funciona?



CORS del lado del cliente



A pesar de que EPP solo se aplica a scripts, los navegadores lo "extienden" a cualquier solicitud de JavaScript: de forma predeterminada, solo tenemos acceso a los recursos de una fuente.







Hmm, pero ... a menudo necesitamos obtener recursos de otra fuente. Quizás nuestra interfaz necesita ir a la API del servidor para cargar datos. Para recuperar de forma segura recursos de otras fuentes, los navegadores implementan un mecanismo llamado CORS.



CORS son las siglas de Cross-Origin Resource Sharing. Aunque los navegadores no permiten recursos de otras fuentes, podemos usar CORS para cambiar esta restricción sin dejar de ser seguros.



Los agentes de usuario (navegadores) pueden usar CORS para permitir solicitudes de origen cruzado que de otro modo se bloquearían en función de algunos encabezados de respuesta HTTP.



Cuando se realiza una solicitud a otra fuente, el cliente agrega automáticamente un encabezado a la solicitud HTTP Origin. El valor de este encabezado es el origen de la solicitud.







Para que el navegador permita recuperar recursos de otra fuente, la respuesta del servidor también debe contener un encabezado específico.



CORS del lado del servidor



Como desarrolladores de backend, podemos permitir que otras fuentes obtengan nuestros recursos al incluir encabezados personalizados que comiencen con Access-Control-*. Según el valor de dichos encabezados, el navegador permite compartir recursos.



Hay varias CORS-headers, pero uno de ellos es una necesidad: Access-Control-Allow-Origin.



El significado de este encabezado determina qué fuentes pueden recibir nuestros recursos.



Si estamos desarrollando un servidor que necesita ser accesible https://mywebsite.com, debemos agregar este dominio al encabezado Access-Control-Allow-Origin.







Excelente. Este encabezado ahora se agrega a la respuesta del servidor enviada al cliente. EPP ya no nos impide recibir recursos a https://api.mywebsite.comtravés de solicitudes enviadas desde https://mywebsite.com.







El mecanismo CORS del navegador comprueba que los valores del Access-Control-Allow-Originencabezado de respuesta y del encabezado de solicitud coincidan Origin.



En este caso, la fuente de nuestra solicitud es https://www.mywebsite.comel encabezado de respuesta especificado en la lista Access-Control-Allow-Origin.







Excelente. Ahora podemos obtener recursos de otras fuentes. ¿Qué sucede si intentamos hacer esto desde una fuente que no figura en la lista Access-Control-Allow-Origin?







Sí, CORS ha bloqueado el acceso a los recursos.



The 'Access-Control-Allow-Origin' header has a value
  'https://www.mywebsite.com' that is not equal 
to the supplied origin. 


En este caso, la fuente https://www.anotherwebsite.comno aparece en Access-Control-Allow-Origin. CORS ha denegado con éxito los datos solicitados.



CORS le permite especificar *fuentes permitidas como un valor. Esto significa que los recursos estarán disponibles para cualquier fuente, así que tenga cuidado.



Access-Control-Allow-OriginEs uno de los muchos títulos que podemos establecer. El desarrollador de back-end puede configurar CORS para permitir (denegar) solicitudes específicas.



Otro título común es Access-Control-Allow-Methods. CORS solo permite solicitudes de otras fuentes que se enviaron utilizando los métodos especificados.







En este caso, solo se permiten las solicitudes enviadas mediante los métodos GET, POST o PUT. Se bloquearán otros métodos como PATCH o DELETE.



CORS los trata de una manera especial cuando se trata de solicitudes enviadas utilizando los métodos PUT, PATCH y DELETE. Estas consultas "complicadas" a veces se denominan consultas de verificación previa.



Solicitudes preliminares



CORS trabaja con dos tipos de solicitudes: simples y provisionales. Lo que es una consulta depende de algunos de sus valores.



Una solicitud es simple si se envía mediante los métodos GET o POST y no contiene encabezados adicionales. Cualquier otra solicitud es preliminar.



De acuerdo, pero ¿qué significa la solicitud previa y por qué se necesitan esas solicitudes?



Antes de enviar la solicitud real, el cliente envía una solicitud preliminar al servidor con información sobre la solicitud real: sobre su método, encabezados adicionales, incluidos Access-Control-Request-*, etc.







El servidor recibe una solicitud provisional y envía una respuesta provisional vacía que contiene encabezados CORS. El navegador recibe una respuesta provisional y comprueba si se permitirá la solicitud real.







Si es así, el navegador envía la solicitud real y recibe los datos en respuesta.







De lo contrario, CORS bloqueará la solicitud previa y no se enviará la solicitud real. Las solicitudes previas son una excelente manera de evitar que se acceda a los recursos y se modifiquen en el servidor. Esto protege al servidor de solicitudes potencialmente no deseadas de otras fuentes.



Para reducir la cantidad de solicitudes repetidas, podemos almacenar en caché la respuesta provisional agregando un encabezado Access-Control-Max-Agea la solicitud CORS. Esto evita volver a enviar la solicitud preliminar.



Cartas credenciales



Las cookies, los encabezados de autorización y los certificados TLS se instalan de forma predeterminada solo para las solicitudes de una única fuente. Sin embargo, es posible que necesitemos usar estos permisos en una solicitud de otra fuente. Quizás queramos incluir cookies en la solicitud que el servidor puede utilizar para identificar al usuario.



Aunque CORS no contiene permisos de forma predeterminada, podemos cambiar esto con un encabezado Access-Control-Allow-Credentials.



Si queremos incluir cookies y otros encabezados de autorización en nuestra solicitud de otra fuente, debemos establecer el campo en un withCredentialsvalor trueen la solicitud y agregar el encabezado Access-Control-Allow-Credentialsa la respuesta.







Hecho, ahora podemos incluir credenciales en nuestras solicitudes de otra fuente.



Espero que el artículo te haya sido útil. Gracias por su atención.



All Articles