Yii2 Parche CORS error 401

A veces no queda otra que aplicar parches horribles para solucionar alguna situación que de otra forma o se gasta mucho tiempo o en cambio no hay forma de hacerlo de manera prolija.

Esta vez al parecer se trata de la segunda opción :(.

El error en cuestión

Básicamente ocurre que cuando Yii lanza una excepción con un código de error, por ej 5xx, 4xx en los encabezados de la petición no se retornan los headers correspodientes al CORS.

Lo que da como resultado que el navegador indique un error como el siguiente:

Lo que en mi caso particular, en Angular (asumo que también debe ocurrir con otros frameworks y librerías).

No permite obtener correctamente los códigos de error en los interceptores y cualquier petición.

Lo que es importante para diferenciar los errores retornados de algún endpoint, de las fallas de autenticación.

Ya que si se obtiene un código 401, el comportamiento esperado sería poder dirigir al usuario a la página de login.

Y en caso de otro tipo de error, mostrar un mensaje aclaratorio correspondiente.

Como no se pudo solucionar

Lo primero que intenté fue modificar el archivo de configuración de Nginx para asegurarse que siempre se agreguen los headers CORS, de forma similar a como se hace en el caso de archivos de imágenes y otros documentos estáticos.

Pero no funcionó, ya que el Access-Control-Allow-Origin se sobrescribía con un valor inválido.

Como si se soluciono

Des pues de buscar un tiempo en internet me encontré con un post que lo explicaba y que también hizo la prueba modificando la configuración del server.

Ese post es el siguiente: https://developpaper.com/yii2-restful-401-nginx-axios-cross-domain-settings/

La solución obtenida hasta el momento es editar directamente un archivo del core del framework

Por lo que localizaremos: vendor/yiisoft/yii2/filters/auth/AuthMethod.php

Y en dicho archivo buscar el método: handleFailure

y dejarlo así:

public function handleFailure($response)
    {
        header('Access-Control-Allow-Origin: *'); //no queda otra por el moemnto
        header('Access-Control-Allow-Headers X-Requested-With,Content-Type,x_requested_with');
        throw new UnauthorizedHttpException('Your request was made with invalid credentials.');
    }

Tal vez luego encuentre alguna solución más elegante, pero por ahora es una escusa para inaugurar una nueva etiqueta #CrotingPrograming!

Una vez guardado, llega la hora de la verdad, y haciendo un console.log del error:

Aparece como debe ser, ¡Que hermosa es la vida!

Que habría que hacer?

Sin dudar reportarlo a la policía del Web Development y de ahí insistir a ver si lo solucionan o proponer una mejor solución en los canales oficiales, por que en la última versión al día de la fecha no es algo que se haya arreglado.

Quiero guardar esta chanchada en mi repo, ¿Que hago?

Fácil, agregamos una excepción en el .gitignore

!vendor/yiisoft/yii2/filters/auth/AuthMethod.php

y si aún así se resiste, se puede usar el comando:

git add vendor/yiisoft/yii2/filters/auth/AuthMethod.php -f

Actualización en API de palabras al azar

En la API pública de palabras al azar, hoy se agregaron algunas mejoras.

La más importante de ellas, es el agregado de un nuevo parámetro ‘l’ que permite definir la longitud de las palabras a ser devueltas por la misma.

La otra modificación se trata de una corrección sobre el filtrado de caracteres.

Ya que en el dataset se podían llegar a encontrar algunos caracteres extraños y saltos de línea que no habían sido filtrados.

También ya no se devuelven letras en minúsculas, por lo que no existen dos o más variaciones de la misma palabra.

Por lo que ahora un ejemplo de llamada a la API con ambos parámetros sería el siguiente:

https://clientes.api.greenborn.com.ar/public-random-word?c=9&l=8

Que debería retornar 8 palabras al azar, con una longitud de 8 caracteres.

API Pública de palabras al azar

Bien, anteriormente he desarrollado un pequeño proyecto de generador de contraseñas, que surgió con la necesidad de utilizar una herramienta propia para dicho propósito y brindar un servicio más en el servidor de Greenborn.

Y la siguiente mejora de dicho proyecto consiste en la generación de contraseñas basadas en palabras.

Para hacer posible dicha mejora se hace necesario contar con una base de datos de palabras (en principio en español) y la posibilidad de consultar una al azar.

Claro que también se podría utilizar para otros propósitos.

Y ya que la API necesitaría contar con un end-point público, creo que también estaría bueno brindar la documentación necesaria para hacer posible su uso por parte de cualquier persona, para el propósito que considere necesario.

¿Cómo se usa?

Su uso es muy sencillo, sólo hace falta hacer una petición GET de la siguiente URL:

https://clientes.api.greenborn.com.ar/public-random-word

A lo cual la petición respondería con una palabra al azar.

También se puede especificar si el resultado debe devolverse en JSON o XML de acuerdo al header content-type pudiendo definirse en application/json o application/xml.

Además si en la URL se agrega el parámetro ?c=x, siendo x un número entre 1 y 100, se puede especificar la cantidad de palabras a retornar.

Condiciones de uso y Limitaciones

  • No se ofrece ninguna garantía con respecto a cualquier tipo de aspecto del servicio ofrecido.
  • El usuario será responsable de cualquier tipo de uso que le de a la API, desligándose Greenborn de cualquier tipo de responsabilidad sobre el mismo.
  • El uso GRATUITO del servicio está limitado a un máximo de 500 consultas por hora, por dirección IP.
  • Cualquier aspecto de las condiciones de uso, podrá ser modificado sin previo aviso, al igual que no se garantiza la disponibilidad del servicio (salvo que acordemos el pago por cuota de uso).
  • Actualmente el dataset es reducido y se ampliará con el tiempo.

Ampliación del dataset

La base de datos de palabras no se cargará a mano, de hecho se realiza de forma semiautomática.

A partir de la carga de archivos de texto plano de libros en español, a lo cual se llegó alrededor de 40k palabras (existiendo variaciones que agregan mayúsculas y minúsculas).

En este caso los libros en español de donde se obtuvieron las palabras, provienen de: http://www.libroteca.net/