Continuando la discusión de OIDC login via Discourse iOS app occasionally fails with csrf_detected on callback:
Hola a todos,
Esta es una observación de seguimiento relacionada con mi hilo anterior sobre fallos de inicio de sesión OIDC iniciados desde navegadores dentro de aplicaciones de iOS. Esa discusión se centró en fallos deterministas de csrf_detected causados por el aislamiento de cookies de WKWebView, que ahora parecen bien entendidos y esperados.
Este tema vinculado trata sobre la claridad para los administradores, no sobre un error.
Observación
Mientras investigaba una serie de fallos de inicio de sesión OIDC, noté que la misma superficie de error en Discourse:
/auth/oidc/callback → /auth/failure?message=csrf_detected
puede corresponder a múltiples causas raíz fundamentalmente diferentes, dependiendo de lo que devolvió el IdP (Proveedor de Identidad).
Solo desde la interfaz de usuario de la aplicación, estos casos son indistinguibles. La diferencia solo es visible al inspeccionar Administrador → Registros → env / params.
Ejemplos vistos en la práctica (Azure / Entra ID)
Además de la pérdida de cookies del navegador dentro de la aplicación, he observado callbacks donde Entra ID devuelve explícitamente errores estructurados como:
El usuario declinó el consentimiento
error=consent_required
error_description=AADSTS65004: User declined to consent to access the app
El usuario canceló el inicio de sesión
error=access_denied
error_subcode=cancel
En ambos casos:
\t•\tAzure identificó al usuario con éxito
\t•\tEl usuario eligió explícitamente no continuar (rechazar / cancelar)
\t•\tDiscourse recibe el callback
\t•\tEl flujo finalmente se resuelve en /auth/failure?message=csrf_detected
Desde la perspectiva de Discourse, este es un comportamiento correcto y seguro: el estado no se puede validar ni completar, pero la razón subyacente es muy diferente a la de una cookie de sesión faltante.
Por qué esto es importante para los administradores
Sin revisar el entorno/parámetros del registro, un administrador que vea fallos repetidos de csrf_detected podría suponer razonablemente:
\t•\tcookies rotas
\t•\tconfiguración incorrecta de SameSite
\t•\tproblemas con el navegador móvil
\t•\tinestabilidad del IdP
…cuando en realidad, algunos de esos fallos son simplemente usuarios que eligen no dar su consentimiento o cancelar la solicitud de Microsoft.
Esta distinción solo se aclara si ya se sabe que se debe inspeccionar la carga del registro sin procesar.
Sugerencia (solo documentación / UX)
No estoy sugiriendo ningún cambio de comportamiento en OmniAuth o en el manejo de CSRF.
Sería útil si la documentación o la guía de solución de problemas notaran explícitamente que:
\t•\tcsrf_detected puede ser el error final para múltiples resultados del IdP ascendente
\t•\tincluyendo acciones explícitas del usuario como cancelar o rechazar el consentimiento
\t•\ty que los administradores deben inspeccionar Administrador → Registros → env / params para distinguir estos casos
Esto facilitaría a los administradores:
\t•\tdiagnosticar correctamente los fallos de inicio de sesión
\t•\tevitar cambios de configuración innecesarios
\t•\ty proporcionar orientación precisa a los usuarios (“cancelaste / rechazaste el consentimiento” frente a “tu navegador bloqueó las cookies”).
Contexto
Para mayor claridad: esto es independiente del problema confirmado del navegador dentro de la aplicación de iOS discutido en el tema vinculado. En ese caso, el IdP nunca llega al punto del consentimiento del usuario, mientras que aquí el IdP informa explícitamente la intención del usuario.
Ambos terminan pareciendo similares a nivel de interfaz de usuario a menos que se examinen los registros.
Gracias por leer; publico esto principalmente como un punto de claridad/datos para la documentación para otros que ejecutan OIDC en entornos con muchos estudiantes donde estos casos ocurren con frecuencia.
Estoy dispuesto a proporcionar ejemplos anonimizados si son útiles.