Con el aumento del número de aplicaciones que utilizan las empresas, y por ende de las diferentes identidades de usuario, hoy en día es fundamental contar con herramientas seguras que permitan identificar a los empleados y gestionar sus derechos. Los mecanismos de autenticación única (más conocidos por el término anglosajón«Single Sign-On»o SSO, por sus siglas en inglés) permiten responder a estas necesidades de seguridad, centralizando las autenticaciones en un servicio especializado (denominado proveedor de identidad o Identity Provider en inglés).
Al centralizar las autenticaciones de los usuarios en un único lugar, se consigue aumentar considerablemente la seguridad de un ecosistema. De hecho, gracias al federador de identidades, la empresa podrá aplicar políticas de seguridad (control de acceso, autenticación multifactorial, política de contraseñas, etc.) y, al mismo tiempo, protegerse en gran medida de los ataques de tipo phishing.
Las aplicaciones empresariales que están integradas con el proveedor de identidad delegan en este la autenticación de los usuarios. A cambio, el proveedor de identidad les proporciona la información del usuario que la aplicación necesita para crear su sesión.
Para que el SSO funcione de forma segura, existen varios protocolos estándar que son compatibles con la mayoría de los proveedores de identidad, tanto de código abierto como comerciales. A continuación, ofrecemos una breve descripción de los distintos protocolos existentes.
SAMLv2
SAMLv2 es, sin duda, el protocolo de federación más utilizado a lo largo de la historia. Fue estandarizado en 2005 por la OASIS. Se basa simplemente en el intercambio de documentos XML entre la aplicación (denominada «Service Provider» en el protocolo SAMLv2) y el proveedor de identidad («Identity Provider»).
Funcionamiento de SAMLv2
Cuando una aplicación federada en SAMLv2 desea autenticar a un usuario, lo redirige al proveedor de identidad configurando una solicitud SAML. Se trata de un documento XML que contiene principalmente la siguiente información:
- El nombre técnico de la aplicación que solicita la autenticación (denominado «entity ID»)
- La URL a la que se redirigirá al usuario una vez que el proveedor de identidad lo haya autenticado (denominada«Assertion Consumer Service URL», a menudo abreviada como ACS)
- Opcionalmente, la solicitud puede incluir una firma, para evitar que sea modificada por un agente malintencionado entre la aplicación y el proveedor de identidad
Una vez que el proveedor de identidad haya recibido la solicitud de la aplicación, procederá a autenticar al usuario. Para ello, podrá basarse en varios criterios (nombre de usuario/contraseña, token Kerberos, notificaciones móviles, reutilización de una sesión existente, etc.).

Figura 1: Esquema de los intercambios durante la autenticación SAMLv2
Tras autenticar al usuario, el proveedor de identidad redirigirá al usuario a la aplicación inicial (utilizando la URL ACS que figuraba en la solicitud SAML) y adjuntará los datos de usuario que necesita la aplicación. Estos datos se incluyen en un nuevo documento XML denominado «respuesta SAML». Este contiene los siguientes elementos:
- El nombre técnico del proveedor de identidad (denominado«entity ID»). Atención: no hay que confundir el entity ID de la aplicación con el entity ID del proveedor de identidad. Ambos son nombres técnicos, ¡pero cada parte del intercambio tiene su propio nombre técnico!
- Un identificador principal del usuario (denominado «SAML Subject» o «NameID»)
- Opcionalmente, puede haber una lista de varios atributos secundarios del usuario (dirección de correo electrónico, apellidos, nombre, entidad, autorizaciones, etc.)
- La firma de la respuesta SAML. Atención: en este caso, la firma no es opcional (a diferencia de la solicitud SAML), ya que la seguridad del protocolo SAML se basa en esta firma.
La aplicación podrá entonces crear una sesión de usuario a partir de la información que haya recibido. El usuario queda autenticado.
Seguridad del protocolo SAMLv2
Es muy importante tener en cuenta que todas las interacciones SAML se realizan a través del navegador del usuario. Por lo tanto, no es necesario establecer ninguna conexión entre la aplicación y el proveedor de identidad; el único requisito es que el usuario pueda acceder a ambos desde su navegador. La otra cara de la moneda es que estas interacciones pueden ser fácilmente leídas o incluso modificadas por una extensión del navegador o una función de JavaScript maliciosa.
Por lo tanto, toda la seguridad de SAMLv2 se basa en la firma de la respuesta SAML. De hecho, las aplicaciones federadas con el proveedor de identidad confían en que este les proporcione la información sobre el usuario que desea autenticarse. La firma permite garantizar que la respuesta no ha sido modificada antes de llegar a la aplicación.
Si la información de los usuarios transmitida por el proveedor de identidad es confidencial, es posible cifrar la respuesta SAML enviada por el IdP para que los atributos no sean legibles. En general, se recomienda cifrar las respuestas enviadas a todas las aplicaciones críticas.
OAuth 2.0/OpenID Connect
OAuth 2.0, OpenID Connect: ¿en qué se diferencian?
Si ya has trabajado con API, seguramente habrás oído hablar del protocolo OAuth. De hecho, este protocolo se creó para permitir la gestión de los permisos de acceso a un recurso por parte de un servicio externo. Es el protocolo que se utiliza, por ejemplo, cuando autorizas a tu cliente de correo electrónico (Outlook/Thunderbird) a acceder a tu cuenta de Gmail en línea. En este ejemplo, Google, una vez que el usuario ha dado su consentimiento a la operación, emitirá un token de acceso (más conocido como Access Token) válido en un ámbito concreto (denominado «scope»). El cliente de correo podrá entonces utilizar este token de acceso para realizar las acciones que el usuario le haya autorizado a realizar dentro de ese ámbito (leer correos, enviar correos, etc.).

Figura 2 : Ejemplo en el que se permite a un cliente de correo electrónico (en este caso, Mozilla Thunderbird) acceder a los mensajes de una cuenta de Google
Por lo tanto, OAuth 2.0 se creó para facilitar el acceso a recursos entre aplicaciones. En este proceso, el usuario se autentica con el único fin de autorizar o no que una aplicación de terceros realice determinadas acciones (enviar correos electrónicos, consultar el calendario, etc.) sobre sus recursos. OAuth no tiene como objetivo autenticar al usuario para que pueda acceder a una aplicación. Por lo tanto, no puede considerarse un protocolo SSO.
Para complementar OAuth 2.0 y dotarlo de las funciones de autenticación SSO que se requieren en el ámbito empresarial, la OpenID Foundation ha introducido un nuevo protocolo:OpenID Connect. Se trata de una extensión de OAuth 2.0 que añade un nuevo token (además del token de acceso): el token de identidad (conocido como ID Token). Este token de identidad contendrá toda la información sobre el usuario necesaria para el funcionamiento de una aplicación, por lo que el protocolo OpenID Connect podrá utilizarse como protocolo de SSO. Este es el protocolo que utilizan los proveedores de identidad en línea, como France Connect para conectarse a los sitios web y aplicaciones de la administración francesa, o los botones «Iniciar sesión con Google», «Iniciar sesión con Facebook», etc.

Figura 3 : Ejemplo en el que se permite a un usuario iniciar sesión en un servicio (en este caso, jeveuxaider.gouv.fr) utilizando bien una autenticación federada (FranceConnect) mediante el protocolo OpenID Connect, bien una autenticación local con nombre de usuario y contraseña
Funcionamiento de OpenID Connect
El estándar OAuth 2.0 define varios flujos, es decir, diferentes procesos que permiten generar un token de acceso. El protocolo OpenID Connect ha incorporado dos de ellos:
- Flujo implícito
- Flujo del código de autorización
El flujo del código de autorización
El flujo de código de autorización es el más utilizado para la autenticación de usuarios. Consiste en dos intercambios entre el cliente y el servidor. Comienza cuando la aplicación que solicita la autenticación (denominada «cliente») redirige al usuario al proveedor de identidad (denominado «servidor de autorización»), incluyendo un sencillo parámetro en la solicitud:
- El ID de cliente (identificador único de la aplicación)
- La URL de redireccionamiento a la que se redirigirá al usuario tras haber sido autenticado por el servidor de autorización
- El tipo de flujo (grant_type): en este caso será «authorization_code»
- Uno o varios ámbitos (como mínimo, el ámbito «openid»).
A continuación, el servidor de autorización autenticará al usuario (nombre de usuario/contraseña, token Kerberos, notificaciones móviles, reutilización de una sesión existente, etc.). Una vez autenticado, el usuario es redirigido de nuevo a la aplicación federada mediante la URL de redirección que se envió como parámetro en la solicitud inicial, junto con un código de un solo uso.

Figura 4: Esquema de los intercambios durante el flujo de autorización (OAuth 2.0/OIDC)
Para obtener el token de acceso y el token de identificación (en el caso de una autenticación OpenID Connect), la aplicación cliente deberá volver a ponerse en contacto con el servidor de autorización, realizando una llamada a la API directamente al proveedor de identidad, con el siguiente parámetro:
- El ID de cliente
- El cliente secreto (un secreto que solo deben conocer la aplicación cliente y el proveedor de identidad)
- El código recibido en el primer intercambio
- La URL de redireccionamiento
- El tipo de flujo («authorization_code»)
El servidor de autorización comprobará que todos estos parámetros sean correctos y que coincidan con los utilizados en el primer intercambio, y devolverá como respuesta dos tokens: un token de acceso (que la aplicación cliente podría utilizar para acceder a recursos de terceros) y un token de identificación (que se podrá utilizar para recuperar la información del usuario y crearle una sesión).
Quizás te preguntes por qué se realizan estos dos intercambios cliente-servidor, en los que primero se obtiene un código intermedio antes de recuperar el token de identidad (que es lo que queremos), mientras que en SAMLv2 solo hay una redirección.
El objetivo del flujo de códigos de autorización en este caso es evitar que los datos confidenciales (el token de acceso, que permite acceder a los recursos de la aplicación, y el token de identificación, que contiene información privada) pasen por el navegador del usuario.
De hecho, el primer paso para recuperar el código es una redirección (que, por lo tanto, tiene lugar en el navegador del usuario) y, por lo tanto, puede ser interceptada. El segundo paso consiste en enviar el código recibido anteriormente para obtener los tokens.
Sin embargo, esta etapa se lleva a cabo enun «canal secundario», es decir, mediante una conexión directa entre la aplicación y el proveedor de identidad. Ambos comparten un secreto común (denominado «cliente secreto») que impide que un atacante que haya interceptado el código durante la primera fase recupere los tokens antes que la aplicación cliente.
El flujo implícito
El flujo implícito es una versión «abreviada» del flujo de código de autorización. De hecho, en lugar de realizar dos intercambios cliente-servidor, solo lleva a cabo el primero. El proveedor de identidad no enviará entonces un código que pueda utilizarse para recuperar, en un segundo intercambio, los dos tokens de acceso e identidad, sino que enviará estos tokens directamente.

Figura 5 : Esquema de los intercambios durante el flujo implícito (OAuth 2.0/OIDC)
Dado que no hay conexiones de«back-channel», el flujo implícito se considera mucho menos seguro que el flujo de código de autorización (todos los datos de los usuarios pasan por el navegador). Por lo tanto, se debe dar prioridad al flujo de código de autorización.
El único caso en el que el flujo implícito resulta útil es cuando no se puede establecer la comunicación entre el proveedor de identidad y la aplicación (por ejemplo, si solo se puede acceder al proveedor de identidad a través de la intranet de la empresa y la aplicación es de tipo SaaS). De hecho, en este caso no es posible la comunicación por «back-channel» del flujo de código de autorización, por lo que habrá que utilizar el flujo implícito.
¿Qué es el PKCE?
Es posible que, al investigar sobre el protocolo OAuth/OpenID, hayas oído hablar de PKCE (siglas de«Proof key for Code Exchange», que podría traducirse como «Clave de prueba para el intercambio de códigos»).
Se trata de una ampliación del flujo de código de autorización, que permite evitar que un script que haya interceptado el código devuelto por el servidor de autorización pueda utilizarlo para obtener los tokens del usuario.
De hecho, este tipo de seguridad es fundamental para las aplicaciones cuyo código se ejecuta directamente en el dispositivo del cliente (aplicaciones en JavaScript puro, React, Angular o aplicaciones móviles/de cliente pesado). En este tipo de aplicaciones, la clave secreta no puede considerarse segura.
El PKCE simplemente generará una cadena de caracteres aleatoria, que se someterá a un proceso de hash. En la primera fase del fallo del código de autorización, la aplicación enviará el resultado de la operación de hash (denominado «código de desafío»). En la segunda fase, la aplicación enviará la cadena de caracteres original (denominada «código de verificación»), que solo ella debe conocer debido a la complejidad de realizar una operación inversa sobre un hash. El servidor de autorización podrá verificar muy fácilmente la validez del par código de desafío/código de verificación.
De este modo, el PKCE permite al servidor de autorización asegurarse de que la aplicación que inició el intercambio es, efectivamente, la que lo finaliza. Por eso, el PKCE es indispensable para todas las aplicaciones que se ejecutan directamente en el lado del cliente, aunque, en general, se recomienda para todas las aplicaciones que utilizan los protocolos OAuth 2.0 u OpenID Connect.
Seguridad de OAuth 2.0/OpenID Connect
OAuth 2.0 y OpenID Connect se basan en el intercambio de tokens (de acceso o de identidad). Estos tokens se emiten en formato JWT (JSON Web Token). Este formato se compone de tres partes:
- El encabezado, que contiene los pocos elementos técnicos utilizados para generar el token
- El cuerpo que contiene la información relevante del token (información del usuario o ámbito al que este tiene acceso).
- La firma criptográfica de las dos primeras partes. Esta firma, generada por el servidor de autorización, debe ser verificada obligatoriamente por la aplicación que recibe el token. Esto le permitirá validar su autenticidad.
Para facilitar el mantenimiento de los certificados de firma criptográfica, el protocolo OAuth define un punto de acceso en el que el servidor de autorización expone las claves públicas de sus certificados de firma. De este modo, cuando se produzca un cambio de certificado, las aplicaciones podrán recuperar automáticamente los nuevos certificados sin necesidad de modificar la configuración de la aplicación.
WS-Fed
El protocolo WS-Fed (abreviatura de «Web Services Federation») es un protocolo de inicio de sesión único (SSO) introducido por un consorcio de grandes empresas informáticas. Se parece mucho al SAML, pero no goza de la misma popularidad que este último. Hoy en día, la única empresa que todavía lo utiliza a gran escala es Microsoft, que lo emplea para la federación de su suite Office, aunque Microsoft tiende a apoyarse cada vez más en OAuth con Azure AD. Por eso, a menos que seas desarrollador de Microsoft (en cuyo caso no estoy seguro de que este artículo te resulte muy útil), este protocolo ya no es realmente recomendable; es preferible SAML, ya que cuenta con más soporte.
Comparación de los distintos protocolos
Todos estos protocolos están muy bien, pero la pregunta que debes hacerte es: ¿cuál es el más adecuado para mi aplicación? A continuación, intentaremos resumir las ventajas y los inconvenientes de cada protocolo en función de los distintos tipos de aplicaciones.
No es necesario que identifique al usuario
Si solo desea permitir que una aplicación de terceros acceda a los recursos de su aplicación, debe utilizar el protocolo OAuth 2.0. Este no es un protocolo de SSO propiamente dicho, pero está diseñado para este tipo de intercambios de datos entre aplicaciones. El usuario siempre podrá dar su consentimiento para autorizar dichos intercambios.
Utilizas una arquitectura SPA
Si desea autenticar a un usuario pero utiliza una arquitectura de «aplicación de página única», como las aplicaciones JavaScript escritas en React.js, Angular o Vue.js, este tipo de aplicaciones, que se ejecutan en el navegador del cliente, se adaptan mucho mejor al protocolo OIDC. De hecho, la gran mayoría de los marcos de trabajo para este tipo de aplicaciones suelen admitir este protocolo de forma prácticamente nativa. Cabe señalar que, en este caso, es obligatorio el flujo de código de autorización con la extensión PKCE.
Utilizas una arquitectura MPA
Si deseas autenticar a un usuario y utilizas una arquitectura de «aplicación multipágina» (con la lógica de la aplicación en el lado del servidor), tienes muchas opciones entre las que elegir. De hecho, puedes encontrar fácilmente bibliotecas que te permiten implementar la autenticación SAMLv2 u OpenID Connect en PHP, Java, Python, JavaScript, etc.
¿Cómo elegir el protocolo adecuado en este caso? Lamentablemente, no hay respuestas prefabricadas; dependerá de varios criterios: qué proveedor de identidades se utiliza en su empresa, las normas establecidas por los equipos que gestionan el SSO, etc. Los propios protocolos tienen sus ventajas e inconvenientes.

En resumen
Hemos visto que existen tres protocolos principales para llevar a cabo la autenticación única:
- SAMLv2
- OpenID Connect (que no debe confundirse con OAuth 2.0, que es un protocolo de autorización y no de autenticación)
- WS-Fed
Dado que el WS-Fed apenas se utiliza y que, en cualquier caso, puede sustituirse por el SAMLv2, es mejor evitarlo en la mayoría de los casos.
Por otra parte, la elección de SAMLv2 puede depender de varios criterios: la arquitectura de la aplicación, el proveedor de identidad, etc. Si utilizas un federador de identidad reciente, debería ser compatible con todos estos protocolos. Si quieres saber un poco más sobre los diferentes federadores de identidad, sus ventajas y sus inconvenientes, te invito a leer este artículo que compara las soluciones de Okta, PingIdentity e Ilex.
Te recomiendo encarecidamente que leas la documentación en línea del federador de identidades que utilices, ya que suele contener ejemplos concretos de integración de SSO. Además, si deseas ver ejemplos prácticos de implementación de SSO en tu lenguaje de programación o en tu marco de trabajo, debes saber que hay cientos de proyectos en GitHub que tratan estos temas
En este artículo se han presentado brevemente los distintos protocolos, aunque cada uno de ellos presenta muchas más sutilezas. Dado que todos estos protocolos son estándar, puedes consultar sus definiciones públicas para ampliar tus conocimientos. Estas definiciones no están pensadas para principiantes, pero resultan muy útiles en cuanto sabes qué buscar:
Por último, la federación de identidades es una buena herramienta para proteger la autenticación en las aplicaciones corporativas, pero no sirve de nada sin políticas de seguridad (autenticación fuerte, control de acceso, evaluación de riesgos, etc.) que permitan determinar con precisión las necesidades de seguridad de una aplicación y la experiencia del usuario. Así, una aplicación como la VPN corporativa, aunque pueda federarse con el IdP, requerirá una autenticación fuerte (con autenticación multifactorial), mientras que otras aplicaciones menos críticas (reservas de salas, planificación de equipos, etc.) podrán utilizar una autenticación transparente (mediante un token Kerberos).
Yannis DUHAMELLE
Consultor de ciberseguridad








