Elegir una estrategia de SSO: SAML vs OAuth2
Es probable que alguna vez hayas iniciado sesión en una aplicación (móvil o web) haciendo clic en el botón «Iniciar sesión con Facebook». Si usas Spotify, Rdio o Pinterest, entonces sabes de lo que estoy hablando.
Como usuario, es probable que no te importe cómo funciona el SSO. Solo quieres usar una aplicación y puedes agradecer una experiencia más fluida y que tengas que recordar menos inicios de sesión y contraseñas.
Para proporcionar a un usuario una experiencia de inicio de sesión único, un desarrollador necesita implementar una solución SSO. A lo largo de los años ha habido muchos intentos de lograr el SSO, pero este artículo se va a centrar en una comparación entre SAML y OAuth2 – una exploración reciente en la que nos embarcamos (afortunadamente saliendo ilesos del otro extremo, pero con mucha información).
Nuestra necesidad de SSO
Estamos trabajando en una plataforma que tendrá varias aplicaciones cliente. Algunas de estas aplicaciones estarán basadas en la web, otras serán nativas, como aplicaciones móviles.
Esta plataforma se desplegará siendo accesible a unos pocos clientes diferentes (propiedad de diferentes organizaciones). Más adelante, se pretende construir aplicaciones adicionales de terceros en torno a esta plataforma.
La plataforma es un front end de un gran sistema empresarial que ya tiene información de identidad sobre las personas que estarían interactuando con él. En lugar de que cada aplicación cliente mantenga su propia base de datos de usuarios con nombres de usuario y contraseñas, parece más apropiado utilizar el SSO.
El inicio de sesión único permitiría al sistema empresarial almacenar de forma segura y poseer todas las credenciales de los usuarios. La plataforma puede establecer una relación de confianza con el servidor de autenticación de la empresa y las aplicaciones cliente pueden ser construidas para utilizar el servidor de autenticación de confianza para autenticar a los usuarios.
Nuestro objetivo era identificar una estrategia e implementación de SSO que pudiera soportar estas necesidades.
Entramos en SAML 2.0
En un principio nos fijamos en SAML 2.0, que es un conjunto de estándares abiertos, uno de los cuales está diseñado específicamente para el SSO.
La especificación SAML 2.0 (en adelante SAML) proporciona un perfil SSO para navegadores web que describe cómo se puede lograr el inicio de sesión único para aplicaciones web. Hay tres actores principales en SAML:
SAML y OAuth2 utilizan términos similares para conceptos similares. Para comparar los términos formales de SAML se enumeran con el equivalente de OAuth2 entre paréntesis.
-
Proveedor de servicios (servidor de recursos): es el servidor web al que se intenta acceder a la información.
-
Cliente – es la forma en que el usuario está interactuando con el Servidor de Recursos, como una aplicación web que se sirve a través de un navegador web.
-
Proveedor de Identidad (Servidor de Autorización) – es el servidor que posee las identidades y credenciales del usuario. Es con quien realmente se autentifica el usuario.
-
A – un usuario abre su navegador web y va a MyPhotos.com que almacena todas sus fotos. MyPhotos.com no maneja la autenticación por sí mismo.
-
B – para autenticar al usuario, MyPhotos.com construye una Authnrequest SAML, la firma, opcionalmente la encripta y la codifica. A continuación, redirige el navegador web del usuario al proveedor de identidad (IdP) para que se autentique. El IdP recibe la solicitud, la descodifica, la descifra si es necesario y verifica la firma.
-
C – Con una Authnrequest válida, el IdP presentará al usuario un formulario de inicio de sesión en el que puede introducir su nombre de usuario y contraseña.
-
D- Una vez que el usuario ha iniciado la sesión, el IdP genera un token SAML que incluye información de identidad sobre el usuario (como su nombre de usuario, correo electrónico, etc). El IdP toma el token SAML y redirige al usuario de vuelta al proveedor de servicios (MyPhotos.com).
-
E – MyPhotos.com verifica el token SAML, lo descifra si es necesario, y extrae la información de identidad sobre el usuario, como quién es y cuáles son sus permisos. MyPhotos.com ahora registra al usuario en su sistema, presumiblemente con algún tipo de cookie y sesión.
-
Servidor de recursos (proveedor de servicios): es el servidor web al que se intenta acceder a la información.
-
Cliente: es la forma en que el usuario interactúa con el servidor de recursos. Puede ser una aplicación web basada en el navegador, una aplicación móvil nativa, una aplicación de escritorio o una aplicación del lado del servidor.
-
Servidor de autorización (proveedor de identidad): es el servidor que posee las identidades y credenciales del usuario. Es con quien el usuario realmente se autentifica y autoriza.
-
A – un usuario abre su navegador web y va a MyPhotos.com que almacena todas sus fotos. MyPhotos.com no maneja la autenticación por sí mismo, por lo que el usuario es redirigido al servidor de autorización con una solicitud de autorización. Al usuario se le presenta un formulario de inicio de sesión y se le pregunta si desea aprobar que el servidor de recursos (MyPhotos.com) actúe en su nombre. El usuario inicia la sesión y es redirigido de nuevo a MyPhotos.com.
-
B: el cliente recibe un código de concesión de autorización como parte de la redirección y lo transmite al cliente.
-
C – el cliente utiliza ese código de concesión de autorización para solicitar un token de acceso al servidor de autorización.
-
D – si el código de concesión de autorización es válido, el servidor de autorización concede un token de acceso. El token de acceso es utilizado por el cliente para solicitar recursos del servidor de recursos (MyPhotos.com).
-
E – MyPhotos.com recibe la solicitud de un recurso y recibe el token de acceso. Para asegurarse de que se trata de un token de acceso válido, envía el token directamente al Servidor de Autorización para que lo valide. Si es válido, el Servidor de Autorización devuelve la información sobre el usuario.
-
F – habiendo validado la solicitud del usuario MyPhotos.com envía el recurso solicitado de vuelta al usuario.
- OAuth 2.0 (sin firmas) es malo para la web
- Outh 2.0 y el camino al infierno
El flujo SAML más común se muestra a continuación:
Aquí hay un escenario ficticio que describe el diagrama anterior:
Al final del proceso el usuario puede interactuar con MyPhotos.com como un usuario registrado. Las credenciales del usuario nunca pasaron por MyPhotos.com, sólo por el proveedor de identidades.
Hay más detalles en el diagrama anterior, pero esto es un nivel alto de lo que está pasando.
Cuando se introdujo por primera vez a SAML, el término «token SAML» surgió una y otra vez. En realidad no es un término en la especificación de SAML, pero la gente seguía usándolo, y su significado era difícil de entender.
Resulta que el término «token de SAML» parece ser una forma coloquial de referirse a la aserción de SAML, a menudo comprimida, codificada, posiblemente encriptada, y por lo general parece una jerigonza. Y una aserción SAML no es más que un nodo XML con ciertos elementos.
Limitación de la aplicación nativa de SAML
SAML soporta los conceptos de bindings. Estos son esencialmente los medios por los que el Proveedor de Identidad redirige al usuario de vuelta al Proveedor de Servicios. Por ejemplo, en el paso D de arriba, el usuario es redirigido de vuelta a MyPhotos.com, pero ¿cómo?
Los dos tipos relevantes de bindings son el HTTP Redirect y el HTTP POST binding definidos en la especificación SAML 2.0. La vinculación HTTP Redirect utilizará una redirección HTTP para enviar al usuario de vuelta al proveedor de servicios, en el caso de nuestro ejemplo: MyPhotos.com.
La vinculación HTTP Redirect es estupenda para mensajes SAML cortos, pero se desaconseja su uso para mensajes más largos como las aserciones SAML. De la wikipedia:
Los mensajes más largos (por ejemplo, los que contienen aserciones SAML firmadas) deben transmitirse a través de otros enlaces como el HTTP POST Binding.
La forma recomendada de utilizar un HTTP POST tiene sus propias rarezas. Por ejemplo, la especificación de SAML recomienda que el paso D de arriba presente un formulario HTML en el que la acción apunte de nuevo al proveedor de servicios.
Puede hacer que el usuario haga clic en otro botón para enviar ese formulario o puede utilizar JavaScript para automatizar el envío del formulario. ¿Por qué hay que enviar un formulario? En mi opinión, SAML 2.0 está mostrando su edad (alrededor de 2005), ya que el formulario aquí sólo existe para que un HTTP POST pueda ser utilizado para enviar el token SAML de vuelta al proveedor de servicios. Lo que en defensa de SAML, en 2005, fue probablemente una decisión necesaria en su momento.
Esto es un problema cuando el cliente no es una aplicación basada en la web, sino una nativa, como una aplicación móvil. Por ejemplo, supongamos que hemos instalado la aplicación MyPhotos para iPhone. Abrimos la aplicación y quiere que nos autentifiquemos con el proveedor de identidad. Una vez que nos autenticamos, el proveedor de identidades necesita enviar el token SAML de vuelta a la aplicación MyPhotos.
La mayoría de las aplicaciones móviles se pueden lanzar a través de una URI personalizada, como, por ejemplo, «my-photos://authenticate», y presumiblemente, el proveedor de identidades envía el formulario que incluye el token SAML a esa URL. Nuestra aplicación MyPhotos se inicia, pero no iniciamos sesión. ¿Qué ocurre?
Las aplicaciones móviles no tienen acceso al cuerpo del HTTP POST. Sólo tienen acceso a la URL que se utiliza para lanzar la aplicación. Esto significa que no podemos leer el token SAML.
En Android: lanzar una aplicación desde una url usando Intents.
En iOS: lanzar una aplicación registrando un esquema URI personalizado.
Sin token SAML, no hay usuario autenticado.
Trabajando en torno a la vinculación HTTP POST de SAML
La limitación de la vinculación HTTP POST para las aplicaciones móviles nativas puede ser trabajada. Por ejemplo, puedes utilizar vistas web incrustadas, en las que escribes código personalizado para ver todo el proceso de autenticación. Al final del proceso, se raspa el HTML de la página y se extrae el token SAML.
Una segunda solución es implementar un servidor proxy que pueda recibir el HTTP POST, extraer el token SAML y, a continuación, crear una URL que incluya el token SAML (por ejemplo: «myphotos://authenticate/?SAMLRequest=asdfsdfsdf»). Y como el token SAML forma parte de la URL, la aplicación MyPhotos puede extraerlo y utilizarlo para iniciar la sesión.
Una tercera solución sería ignorar la recomendación de la especificación de no utilizar el enlace HTTP Redirect. Esto es muy tentador, pero es difícil deshacerse de la sensación de que estás caminando en un campo de minas, con la esperanza de no dar un paso en falso.
Otro enfoque que evitó las soluciones de trabajo por completo es no confiar en SAML, sino buscar otro enfoque, como OAuth 2.0.
Entre OAuth 2.0
A diferencia de SAML, OAuth 2.0 (en adelante OAuth2), es una especificación cuya tinta apenas se ha secado (alrededor de finales de 2012). Tiene la ventaja de ser reciente y tiene en cuenta cómo ha cambiado el mundo en los últimos ocho años.
Los dispositivos móviles y las aplicaciones nativas prevalecen hoy en día de una manera que SAML no podía anticipar en 2005.
Los jugadores básicos con OAuth2 son:
SAML y OAuth2 utilizan términos similares para conceptos similares. Para comparar los términos formales de OAuth2 se enumeran con el equivalente de SAML entre paréntesis.
A un alto nivel, el flujo de OAuth2 no es tan diferente del flujo SAML anterior:
Vamos a recorrer el mismo escenario que recorrimos antes con SAML:
Este es el flujo más común de OAuth2: el flujo de código de autorización. OAuth2 proporciona otros tres flujos (o lo que ellos llaman concesiones de autorización) que funcionan para escenarios ligeramente diferentes, como aplicaciones javascript de una sola página, aplicaciones móviles nativas, aplicaciones de escritorio nativas, aplicaciones web tradicionales y aplicaciones del lado del servidor en las que un usuario no está directamente involucrado pero te ha concedido permiso para hacer algo en su nombre.
La gran ventaja con los flujos de OAuth2 es que la comunicación desde el servidor de autorización de vuelta al cliente y al servidor de recursos se realiza a través de redirecciones HTTP con la información del token proporcionada como parámetros de consulta. OAuth2 tampoco asume que el cliente es un navegador web, mientras que el perfil SAML Web Browser SSO por defecto sí lo hace.
Las aplicaciones móviles nativas funcionarán sin más. No es necesario hacer arreglos.
La frase favorita de OAuth2: Out of Scope
La especificación de OAuth2 no prescribe cómo funciona la comunicación entre el Servidor de Recursos y el Servidor de Autorización en un montón de situaciones, como la validación de un token. Tampoco dice nada sobre qué información debe devolverse sobre el usuario o en qué formato.
Hay bastantes puntos en los que la especificación OAuth2 establece que las cosas están «fuera del ámbito de esta especificación». Esto ha provocado críticas a la especificación OAuth2 porque deja muchas cosas a la implementación, lo que podría llevar a implementaciones incompatibles en algún momento.
OAuth2, es todavía muy joven, y ya tiene una adopción generalizada con los gustos de Google, Facebook, Salesforce, y Twitter por nombrar algunos. La verdadera belleza de OAuth2 es su simplicidad. De hecho, el perfil básico de OpenID Connect, que se basa en OAuth2, completa algunas de las áreas que la propia especificación de OAuth2 no define.
OAuth2: No requiere firmas digitales por defecto
OAuth2 no requiere firmar los mensajes por defecto. Si quieres añadir eso, siéntete libre, pero fuera de la caja, la especificación funciona sin ella. Lo que sí prescribe es que todas las peticiones se hagan a través de SSL/TLS.
Esto ha causado conmoción en el pasado:
Habiendo trabajado con OAuth2 y OAuth1 en el pasado, puedo decir que OAuth2 es mucho más sencillo que OAuth1 (y más agradable de trabajar). La interoperabilidad y el descubrimiento automático de servicios puede ser algo útil en el futuro, pero ahora mismo, no es algo que estemos buscando.
Es posible que nos pidan que firmemos los mensajes una vez que el equipo de seguridad de la empresa haga la auditoría final de la implementación de OAuth2, pero por ahora, OAuth2 se ajusta a nuestros objetivos actuales de una manera más estandarizada que SAML. También es mucho más sencillo.
Si cada aplicación tiene un servidor web seguro que la respalda, entonces la firma funciona muy bien, pero cuando no es así el problema se vuelve más matizado. ¿Cómo almacenas tus claves de forma segura en el navegador para aplicaciones JS basadas en el navegador o en aplicaciones móviles nativas?
Si buscas en Google descompilar aplicaciones de iOS y Android se te hundirá el corazón. Tus claves realmente no son tan seguras si no puedes poseer y asegurar el dispositivo.
OAuth2 es para Autorización, no para Autenticación
El «auth» en OAuth sí significa «Autorización» y no «Autenticación». El pedante que hay en ti puede estar sonriendo. ¡Me has pillado!
Pero – sí, ¡siempre hay un pero! Aunque el término OAuth es bastante reciente, el hecho de que «auth» signifique autorización parece un poco anacrónico. Ya se está utilizando para lograr SSO en la naturaleza (gracias a los gustos de Facebook, Twitter, Salesforce y Google y miles de sitios que los utilizan para autenticar y autorizar a los usuarios).
La mayor queja que he visto es en la falta de prescripción y los abundantes usos «fuera del alcance» en la especificación OAuth2. El hecho de que el perfil básico de OpenID Connect esté construido directamente sobre OAuth2 debería ser suficiente para disipar el mito de que OAuth2 no se puede utilizar para la autenticación.
Lo que significaba una palabra hace seis años es mucho menos importante que lo que puede abarcar hoy.
Resumen
SAML tiene una característica de la que carece OAuth2: el token SAML contiene la información de identidad del usuario (debido a la firma). Con OAuth2, no se obtiene eso de forma inmediata, y en su lugar, el Servidor de Recursos necesita hacer un viaje de ida y vuelta adicional para validar el token con el Servidor de Autorización.
Por otro lado, con OAuth2 se puede invalidar un token de acceso en el Servidor de Autorización, y deshabilitarlo para el acceso posterior al Servidor de Recursos.
Ambos enfoques tienen buenas características y ambos funcionarán para SSO. Hemos probado ambos conceptos en múltiples lenguajes y varios tipos de aplicaciones. Al final del día OAuth2 parece ser un mejor ajuste para nuestras necesidades (ya que no hay una infraestructura SAML existente para utilizar).
OAuth2 proporciona una solución más simple y estandarizada que cubre todas nuestras necesidades actuales y evita el uso de soluciones para la interoperabilidad con aplicaciones nativas.
A medida que esto comienza a desarrollarse y trabajamos con varios equipos de seguridad vamos a ver hasta qué punto esto se mantiene.
Hasta ahora, todo bien.