Estoy buscando mejorar nuestra postura de seguridad y, como parte de eso, necesitamos evitar usar credenciales secretas siempre que sea posible.
Desafortunadamente, el plugin OIDC requería una credencial de secreto de cliente para acceder al endpoint /userinfo, y no pude configurar mi foro con él habilitado.
Afortunadamente, la especificación OIDC está definida de tal manera que no requiere el uso de tokens secretos.
Si nos ceñimos al flujo id_token, el IdP nos enviará toda la información que necesitamos para autenticar a un usuario sin tener que volver a contactar al IdP.
Esto es seguro porque la redirección está configurada en el IdP y no tenemos que preocuparnos de que el token bearer se reenvíe al destino incorrecto.
He creado un parche para el plugin OIDC para admitir el flujo id_token y he enviado una pull request aquí:
La PR no está completamente terminada ya que todavía necesita pruebas unitarias, pero está prácticamente lista y he confirmado que funciona correctamente con Azure AD (Entra ID).
Como referencia, aquí está la documentación para el plugin OIDC:
Creo que lo que describes aquí es el flujo implícito de OpenID Connect, que funciona sin comunicación de servidor a servidor y, por lo tanto, no necesita un secreto compartido. En su lugar, toda la información se transmite a través de las redirecciones HTTP, y el ID token se verifica criptográficamente utilizando las claves públicas del Documento de Descubrimiento.
Eso está bien, y creo que es una solicitud de función válida. Pero es un sistema muy diferente a nuestro plugin actual, que utiliza el flujo de código de autorización. Este flujo utiliza comunicación de servidor a servidor con un secreto compartido, y por lo tanto no se necesita ninguna verificación criptográfica del id_token. Esto es más simple en algunos aspectos, pero más complejo en otros.
Importante: no podemos simplemente cambiar la implementación predeterminada en el plugin. Los sitios que utilizan el flujo de código de autorización necesitan seguir utilizándolo. Si mal no recuerdo, muchos proveedores de identidad ni siquiera admiten el Flujo Implícito.
Así que creo que hay dos caminos a seguir aquí:
Añadimos soporte para el “flujo implícito” en el plugin OIDC, pero lo convertimos en algo opt-in. Creo que es poco probable que aceptemos una PR que introduzca la gema openid-connect como dependencia de Discourse core, por lo que tendría que implementarse dentro de nuestra estrategia actual.
El plugin discourse-lti (integración de herramientas de aprendizaje) puede ser una fuente útil de inspiración, porque el protocolo LTI se basa en el flujo implícito de OIDC. La lógica de decodificación del id_token está aquí
o alternativamente
Construyes el flujo implícito como un plugin totalmente nuevo. En este caso, serías libre de hacer lo que quieras en términos de implementación (pero también tendrías que mantenerlo tú mismo)
También vale la pena señalar que el “Flujo Implícito” de OIDC aumenta la superficie de ataque para ataques CSRF y la exposición de tokens:
Creo que todavía puede tener sentido para algunas situaciones. Pero parece que el flujo de Código de Autorización (el predeterminado de Discourse) con PKCE (opcional en Discourse) es la forma más recomendada de usar OIDC.
Creo que todavía puede tener sentido en algunas situaciones. Pero parece que el flujo de Código de Autorización (el predeterminado de Discourse) con PKCE (opcional en Discourse) es la forma más recomendada de usar OIDC.
Esto es muy interesante: hasta ahora no entendía completamente PKCE. Según mi lectura de la documentación de Auth0, parece que (en ciertas configuraciones) este flujo tiene las ventajas del flujo implícito (sin secreto de cliente) sin ninguno de los inconvenientes.
¿Es esto quizás algo que se puede hacer en su lugar? Parece que es tan simple como eliminar el parámetro client_secret del endpoint /token.
Y, en última instancia, mi principal preocupación es simplemente eliminar el requisito de un secreto de cliente
diff --git a/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb b/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb
index 410a88f46dc..e74ee360aae 100644
--- a/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb
+++ b/plugins/discourse-openid-connect/lib/omniauth_open_id_connect.rb
@@ -73,6 +73,11 @@ module OmniAuth
)
options[:client_options][:auth_scheme] = :request_body
end
+
+ # Si estamos usando PKCE y no hay client_secret, usamos el esquema de autenticación request_body.
+ if options[:pkce] && options[:client_secret].empty?
+ options[:client_options][:auth_scheme] = :request_body
+ end
end
def request_phase
La URI de redirección está configurada en el panel de control de Azure de la siguiente manera: