Todo el que haya integrado un login «a mano» sabe dónde duele: OAuth2 mal configurado, tokens que se filtran y un IdP de terceros que cobra por usuario o elimina una feature en el próximo release. Nos cansamos de eso y construimos Curupira.

Por qué demonios construir nuestro propio IdP
La autenticación es una de esas cosas que nadie quiere reinventar hasta que lo necesita. Nuestro caso era multi-tenant: varias aplicaciones, cada una con sus usuarios, roles y reglas. Las opciones listas para usar o eran caras por usuario, o nos ataban a decisiones que no controlábamos. Construir nuestro propio IdP implica asumir una responsabilidad seria, pero nos dio lo que faltaba: control total sobre las claves, los tokens y la política de seguridad. Curupira es un Identity Provider OAuth2 + OpenID Connect, listo para producción, con issuer predeterminado en auth.dwcorp.com.br y licencia MIT.
Rust no fue una elección por moda
Escribir un IdP en Rust parece exhibicionismo hasta que recuerdas lo que hace un IdP: manipula secretos, valida tokens y se ejecuta en el camino crítico de cada solicitud autenticada. Aquí, las garantías de memoria y la ausencia de sorpresas en runtime compensan el esfuerzo. El stack es Rust + Cargo, con PostgreSQL mediante SQLx, lo que significa queries verificadas en tiempo de compilación y migrations versionadas. Si la query falla, falla en el build, no a las tres de la mañana en producción.
PKCE obligatorio y cero atajos de seguridad
La decisión que más define a Curupira: PKCE es obligatorio. No es opcional y no existe un flag para desactivarlo. Flujo Authorization Code con PKCE S256 (RFC 7636) para todos, ya sean clientes públicos o no. A eso sumamos contraseñas con Argon2id, protección CSRF y endpoints de token e introspección protegidos por API key. El proyecto sigue la RFC 9700, la BCP de seguridad para OAuth2; es decir, las buenas prácticas actuales, no lo que era aceptable en 2015. La idea es simple: hacer que el camino seguro sea el único camino.
Multi-tenant de verdad: una clave RSA por aplicación
Multi-tenant suele ser un adjetivo de marketing. En Curupira es arquitectura: cada aplicación tiene su propio par de claves RSA. Los JWT se firman con RS256, con rotación de claves. Esto significa que comprometer o rotar la clave de una aplicación no afecta a las demás. Sobre esta base funciona un RBAC con roles específicos por aplicación y grupos de roles, para que puedas modelar permisos sin convertir cada tenant en un caso especial. Discovery de OIDC, ID tokens, UserInfo, introspección y logout están incluidos.
Compatible con FusionAuth, con logs en tres capas
Una decisión pragmática: Curupira fue diseñado para ser compatible con FusionAuth. Esto reduce la fricción para quienes ya vienen de ese entorno y nos ofrece un vocabulario conocido en lugar de obligarnos a inventar el nuestro. La observabilidad tampoco quedó fuera: hay tres capas de logs: intentos de login, event logs y audit logs. Cuando algo sale mal en una autenticación, es posible reconstruir lo sucedido. Y, a partir de la v0.8, hay un dashboard administrativo desarrollado con Nuxt.js (Vue) y @nuxt/ui, porque administrar tenants y claves desde la línea de comandos cansa rápidamente.
Lo que ya funciona y lo que viene después
Seamos honestos: Curupira es un producto en evolución. Las fases 0 y 1 —infraestructura y gestión de tenants— ya están listas. Las fases 2 a 5 están en el mapa: gestión de aplicaciones, usuarios y roles; logging y monitorización; MFA; verificación del correo electrónico, y webhooks. Es un roadmap por fases precisamente porque preferimos entregar cada capa bien hecha en lugar de lanzar todo de una vez y cruzar los dedos.
La autenticación es aburrida cuando funciona y catastrófica cuando no. Construir Curupira fue apostar por tener bajo nuestro control este componente crítico: en Rust, con PKCE obligatorio y una clave por tenant. Hasta ahora, la apuesta sigue en pie.



