SAML 2.0: el estándar que inventó el single sign-on web
Cómo SAML 2.0 federa la identidad hacia apps web — los roles IdP/SP/usuario y el trust vía metadata XML, los flujos SP-initiated vs IdP-initiated, los bindings HTTP-Redirect/POST/Artifact, la anatomía de una SAML Assertion (Subject, Conditions, AuthnStatement, AttributeStatement), firma y cifrado, y cuándo SAML sigue siendo la opción correcta frente a OAuth/OIDC.
De almacenar la identidad a moverla
En el artículo de servicios de directorio establecimos dónde viven las identidades. Ahora las movemos. SAML 2.0 es el primer protocolo de nuestro stack — el que tomó una identidad sentada en un directorio corporativo y la hizo utilizable para iniciar sesión en una aplicación que el directorio no posee. Es el abuelo de la federación web, un estándar de OASIS finalizado en 2005, y a pesar de tener dos décadas todavía autentica una proporción asombrosa del software empresarial cada día.
El problema que SAML resolvió es el que todo empleado siente: tienes una identidad corporativa, pero docenas de aplicaciones, muchas de ellas SaaS corriendo en la infraestructura de otro. Sin federación, cada app necesita su propia contraseña — un desastre de seguridad y usabilidad. La respuesta de SAML: deja que un sistema confiable te autentique, y deja que cada aplicación confíe en la palabra de ese sistema en lugar de correr su propio login. Esa “palabra” es un documento XML firmado llamado assertion, y entender SAML es sobre todo entender cómo se produce, transporta y verifica ese documento.
Los tres roles y la confianza entre ellos
SAML tiene exactamente tres actores, y tenerlos claros hace que todo lo demás encaje:
- Proveedor de Identidad (IdP): el sistema que autentica al usuario y emite las assertions. Está respaldado por el directorio — Entra ID, Okta, ADFS, Ping. El IdP es donde la contraseña (o el MFA) realmente se verifica.
- Proveedor de Servicio (SP): la aplicación que el usuario quiere alcanzar. Terceriza la autenticación al IdP y consume la assertion. Tus apps SaaS son SPs.
- Principal (usuario): el ser humano autenticado, que experimenta todo esto como “haz clic en la app, ya estás dentro”.
La confianza se establece con metadata XML
Un SP no puede simplemente confiar en cualquier assertion que aparezca — tiene que saber, de antemano y criptográficamente, en qué IdP confiar y cómo verificar sus firmas. Ese arranque ocurre mediante el metadata SAML: un documento XML que cada parte publica describiéndose a sí misma. El metadata contiene:
- El entityID — el identificador único de la parte (normalmente una URL).
- Los endpoints — a dónde enviar y recibir mensajes SAML (p. ej. la URL del Assertion Consumer Service del SP).
- Los certificados de firma — la clave pública que el otro lado usa para verificar firmas.
- Los bindings y formatos de NameID soportados.
Montar una integración SAML es, en el fondo, intercambiar metadata: el IdP y el SP importan el metadata XML del otro, y desde ese momento cada uno conoce la identidad, endpoints y claves públicas del otro. Esta confianza preestablecida y basada en certificados es justo por lo que un SP puede creer una assertion sin contactar nunca directamente al directorio del usuario — la confianza se cableó de antemano.
sequenceDiagram accTitle: Establecer la confianza SAML mediante intercambio de metadata accDescr: Antes de que ocurra cualquier login, el proveedor de identidad y el proveedor de servicio intercambian metadata XML. El IdP comparte su metadata con su entityID, endpoint de SSO y certificado de firma. El SP comparte su metadata con su entityID, URL del Assertion Consumer Service y certificado. Cada parte importa el metadata del otro, y desde ese punto se establece la confianza mutua para que pueda ocurrir el single sign-on. participant SP as Proveedor de Servicio participant IdP as Proveedor de Identidad IdP->>SP: Metadata del IdP (entityID, URL SSO, cert de firma) SP->>IdP: Metadata del SP (entityID, URL ACS, cert) Note over SP,IdP: Cada uno importa el metadata del otro Note over SP,IdP: Confianza mutua establecida — ya puede ocurrir el SSO
Los dos flujos: SP-initiated vs IdP-initiated
Hay dos formas en que una sesión de SSO puede comenzar, y la diferencia importa tanto para la UX como para la seguridad.
SSO SP-initiated
El usuario empieza en la aplicación. Este es el flujo común y recomendado:
sequenceDiagram accTitle: Single sign-on SAML SP-initiated accDescr: El usuario solicita un recurso protegido en el proveedor de servicio. El SP genera una solicitud de autenticación y redirige el navegador del usuario al proveedor de identidad. El IdP autentica al usuario (contraseña más MFA), construye una assertion SAML firmada, y la postea de vuelta a través del navegador al Assertion Consumer Service del SP. El SP valida la firma y las condiciones, crea una sesión y otorga acceso. actor U as Usuario (navegador) participant SP as Proveedor de Servicio (app) participant IdP as Proveedor de Identidad U->>SP: Solicita recurso protegido SP->>U: Redirección con AuthnRequest U->>IdP: Entrega AuthnRequest IdP->>U: Autentica (contraseña + MFA) IdP->>U: Assertion firmada (HTTP-POST) U->>SP: POST de la assertion al ACS SP->>SP: Valida firma + condiciones SP->>U: Sesión creada, acceso otorgado
Lectura del flujo: el SP emite un AuthnRequest y redirige el navegador al IdP. El IdP autentica al usuario, construye una assertion firmada, y envía el navegador de vuelta a la URL del Assertion Consumer Service (ACS) del SP llevando esa assertion. El SP la valida y crea una sesión local. Crucialmente, la assertion viaja a través del navegador del usuario — SAML es un protocolo de front-channel mediado por el navegador — y el SP correlaciona la respuesta con la solicitud que inició, lo que cierra clases enteras de ataques de inyección.
SSO IdP-initiated
Aquí el usuario empieza en el IdP — un portal de mosaicos de apps — y hace clic en uno. El IdP envía una assertion no solicitada directo al ACS del SP, sin un AuthnRequest previo. Es cómodo (la clásica experiencia de “lanzadera de apps”) pero más débil: como no hay una solicitud contra la cual correlacionar, una assertion capturada en tránsito es más fácil de replay, y el SP tiene menos contexto para validar. La guía moderna es preferir SP-initiated para cualquier cosa sensible y tratar IdP-initiated como una función de conveniencia que se habilita deliberadamente, no por defecto.
Bindings: cómo viajan los mensajes SAML
Un binding es el mecanismo de transporte — cómo un mensaje SAML se mapea sobre HTTP. SAML 2.0 define tres que encontrarás:
| Binding | Cómo funciona | Uso típico |
|---|---|---|
| HTTP-Redirect | El mensaje se comprime y se coloca en el query string de la URL | Enviar el corto AuthnRequest del SP al IdP |
| HTTP-POST | El mensaje se codifica en base64 en un campo de formulario oculto, auto-enviado por el navegador | Devolver la assertion del IdP al SP (las assertions son muy grandes para una URL) |
| HTTP-Artifact | El navegador lleva solo una referencia (“artifact”); el SP obtiene la assertion real por un canal trasero | Configuraciones de alto aseguramiento que mantienen la assertion fuera del front channel |
El patrón práctico en la abrumadora mayoría de los despliegues es Redirect para la solicitud, POST para la assertion: el AuthnRequest es lo bastante pequeño para viajar en una URL, mientras que la assertion — llena de XML firmado — es demasiado grande, así que regresa como un formulario POST auto-enviado. Artifact es más raro pero valioso cuando no quieres que la assertion pase por el navegador en absoluto; en su lugar el navegador lleva un identificador de un solo uso que el SP canjea directamente con el IdP, manteniendo la carga sensible en un canal servidor-a-servidor.
Anatomía de una SAML assertion
La assertion es el corazón de SAML — la nota firmada en sí. Es un documento XML con cuatro partes que deberías poder reconocer de inmediato:
<saml:Assertion ID="_a1b2c3" IssueInstant="2026-06-10T09:00:00Z">
<saml:Issuer>https://idp.example.com</saml:Issuer>
<ds:Signature>...</ds:Signature>
<saml:Subject>
<saml:NameID Format="...emailAddress">sara@example.com</saml:NameID>
<saml:SubjectConfirmation Method="...bearer">
<saml:SubjectConfirmationData
Recipient="https://sp.example.com/acs"
NotOnOrAfter="2026-06-10T09:05:00Z"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2026-06-10T08:59:00Z"
NotOnOrAfter="2026-06-10T09:05:00Z">
<saml:AudienceRestriction>
<saml:Audience>https://sp.example.com</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2026-06-10T09:00:00Z"
SessionIndex="_sess789">
<saml:AuthnContext>
<saml:AuthnContextClassRef>...PasswordProtectedTransport</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="department">
<saml:AttributeValue>Engineering</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>Cada bloque responde una pregunta distinta:
- Subject — quién es el tema de la assertion. El
NameIDes el identificador (aquí un correo), ySubjectConfirmationdice cómo el SP puede confirmar que el sujeto es el portador, más elRecipientyNotOnOrAfterque la acotan a este SP y este momento. - Conditions — cuándo y para quién es válida la assertion.
NotBefore/NotOnOrAfterdefinen una ventana de validez ajustada (normalmente minutos), yAudienceRestrictionnombra el SP exacto para el que la assertion está destinada — el SP debe rechazar una assertion destinada a otro. - AuthnStatement — cómo se autenticó el usuario.
AuthnInstantes cuándo,AuthnContextClassRefdescribe el método (p. ej. contraseña sobre TLS, o un contexto de MFA), ySessionIndexse ata a la sesión del IdP — esencial para el single logout después. - AttributeStatement — qué más debe saber el SP: atributos como departamento, grupos o roles, obtenidos del directorio, que el SP usa para la autorización.
Una sutileza estructural que vale la pena interiorizar: la assertion normalmente viaja envuelta en un sobre <samlp:Response>, y puede firmarse la respuesta, la assertion, o ambas. Esa distinción suena pedante pero lo es todo para la seguridad — un SP que verifica solo la firma de la respuesta mientras lee los atributos de la assertion dejó justo el hueco que explota el XML Signature Wrapping. La regla que lo previene es simple de enunciar y fácil de equivocar: valida la firma sobre el elemento que realmente consumes, y asegúrate de que ese elemento firmado sea aquel cuyo contenido confías.
Firma y cifrado
El modelo de confianza de SAML es criptográfico, y se divide limpiamente en dos preocupaciones.
La XML Signature provee integridad y autenticidad. El IdP firma la assertion (o toda la respuesta) con su clave privada; el SP verifica con el certificado público del IdP del metadata. Una firma válida prueba dos cosas: la assertion realmente vino del IdP confiable, y ni un solo byte fue alterado en tránsito. La firma es, en cualquier despliegue sensato, obligatoria — una assertion sin firmar es una nota que cualquiera pudo haber escrito.
La XML Encryption provee confidencialidad. El IdP puede cifrar la assertion (o atributos específicos) con la clave pública del SP, para que solo el SP pueda leerla. Esto importa porque la assertion pasa por el navegador del usuario, donde podría inspeccionarse; si lleva atributos sensibles (un documento de identidad, un rango salarial, un rol de salud), el cifrado los mantiene privados. El cifrado es opcional y se usa selectivamente — la firma es sobre ¿puedo confiar en esto?, el cifrado es sobre ¿quién más puede leer esto?
Los riesgos de seguridad que vale conocer
La dependencia de SAML en XML complejo ha producido una familia reconocible de ataques, todos catalogados en el OWASP SAML Security Cheat Sheet:
- XML Signature Wrapping (XSW): un atacante reestructura el XML para que el SP valide una firma legítima pero lea contenido controlado por el atacante. Se defiende validando que la firma realmente cubra el elemento que consumes.
- Validación de firma ausente o parcial: aceptar assertions cuya firma no se verifica, o verificar solo la respuesta y no la assertion. El error de implementación SAML número uno.
- Confusión de Audience/Recipient: no confirmar que la assertion fue acuñada para tu SP, permitiendo que una assertion de una app se replay en otra.
- Replay: reusar una assertion capturada dentro de su ventana de validez — mitigado con vidas cortas,
NotOnOrAfterde un solo uso, y rastreo de IDs de assertion.
El hilo conductor: SAML es solo tan seguro como el rigor de la validación del SP. El protocolo es sólido; la mayoría de los fallos del mundo real son SPs que validan de menos.
Single Logout: la mitad difícil
SAML también define el Single Logout (SLO) — terminar las sesiones de un usuario en todos los SPs federados desde una sola acción. El SessionIndex del AuthnStatement es lo que lo hace concebible: ata cada sesión del SP de vuelta a la sesión del IdP, así que cuando el usuario cierra sesión el IdP puede emitir mensajes LogoutRequest a cada SP que tenga una sesión bajo ese índice. En teoría, un clic termina limpiamente cada sesión federada.
En la práctica, el SLO es notoriamente poco fiable. Requiere que cada SP implemente los endpoints de logout correctamente, esté alcanzable en el momento del logout, y honre la solicitud — y un solo SP que se porte mal o esté caído rompe la cadena, dejando vivas sesiones que el usuario cree cerradas. Por eso muchas organizaciones tratan el SLO como best-effort y se apoyan en vidas de sesión cortas y revocación en el IdP como el control real. La lección se generaliza mucho más allá de SAML: federar el login es mucho más fácil que federar el logout, un tema que regresa en OIDC. Distribuir el inicio de la confianza es simple; coordinar su fin simultáneo entre sistemas independientes es genuinamente difícil.
Montar una integración SAML en la práctica
Dejando la teoría, ¿qué implica realmente levantar una conexión SAML? Los pasos reconocibles que siguen los profesionales, en orden:
- Intercambiar metadata: importar el metadata del IdP en el SP y el del SP en el IdP — o configurar a mano entityID, URL de ACS y certificados cuando no se ofrece una URL de metadata.
- Elegir el formato de NameID: decidir qué identifica de forma única y estable al usuario entre sistemas (correo, o un ID opaco persistente). Un NameID que no coincide es la causa número uno de “autentica, pero el SP no reconoce al usuario”.
- Mapear atributos: configurar qué atributos del directorio libera el IdP (departamento, grupos, roles) y los nombres exactos que el SP espera. Este mapeo de atributos es donde de verdad se va la mayor parte del tiempo de integración.
- Configurar firma y cifrado: asegurar que las assertions estén firmadas, decidir si cifrar, y confirmar que ambos lados coinciden en los algoritmos.
- Probar los bordes: primer login, re-login, clock skew, y — crítico — rotación de certificados.
La sabiduría de campo es contundente: la mayoría de las quejas de “SAML es inestable” rastrean a errores de mapeo de atributos o certificados vencidos, no al protocolo. Documenta las URLs de metadata y las fechas de vencimiento de certificados en algún lugar monitoreado, prefiere assertions firmadas con restricciones de audiencia ajustadas y vidas cortas, y valida con rigor del lado del SP. Haz eso y SAML es aburridamente fiable; sáltatelo y estarás depurando bloqueos misteriosos en cada ciclo de certificados.
Cuándo SAML sigue siendo la opción correcta
Los protocolos más nuevos (OAuth 2.0 y OIDC, los próximos dos artículos) son más ligeros, basados en JSON y mejor adaptados a móvil y APIs. Entonces, ¿SAML es legacy? No — es especializado, y en su especialidad a menudo sigue siendo la mejor herramienta:
- SSO de plantilla empresarial: prácticamente todo SaaS empresarial soporta SAML, y los IdP corporativos (Entra ID, Okta, Ping) lo hablan con fluidez. Para empleados iniciando sesión en apps de negocio, SAML es el camino de menor resistencia y mayor compatibilidad.
- Federación B2B: cuando dos organizaciones necesitan dejar entrar a los empleados de una en los sistemas de la otra, la confianza basada en metadata y anclada en certificados de SAML entre dos empresas es madura y bien entendida.
- Entornos con cumplimiento pesado: los sectores regulados con requisitos de auditoría profundos a menudo tienen SAML profundamente incrustado, con controles establecidos y familiaridad de los evaluadores — cambiar de protocolo conlleva un riesgo que la regulación no recompensa.
Dónde SAML es la herramienta equivocada es igual de claro: login de consumidor a escala, apps móviles nativas y autorización API-a-API, donde el XML y las redirecciones de navegador son torpes. Ese es justo el espacio que OAuth 2.0 y OIDC poseen. El contraste de un vistazo:
| Dimensión | SAML 2.0 | OAuth 2.0 / OIDC |
|---|---|---|
| Formato de datos | XML | JSON / JWT |
| Nació para | SSO web empresarial | Delegación de autorización; login de consumidor y móvil |
| Transporte | Redirecciones de navegador + POST | HTTP/REST — funciona para APIs y apps nativas |
| Punto dulce | Plantilla y SaaS B2B | Consumidor, móvil, apps de página única, acceso a APIs |
| Huella empresarial | Ubicuo, profundamente incrustado | Dominante para todo lo nuevo |
En la práctica las organizaciones grandes corren ambos — SAML para el patrimonio empresarial establecido, OIDC para todo lo nuevo — y un profesional de IAM tiene que dominar el equilibrio en lugar de ser dogmático sobre un protocolo.
Recapitulación
SAML 2.0 es SSO web federado mediante assertions XML firmadas:
- Tres roles: el IdP autentica y emite assertions, el SP las consume, el usuario experimenta un login fluido — con la confianza preestablecida al intercambiar metadata XML (entityID, endpoints, certificados).
- Dos flujos: SP-initiated (empezar en la app, recomendado) e IdP-initiated (empezar en un portal, cómodo pero más débil).
- Tres bindings: HTTP-Redirect (la solicitud), HTTP-POST (la assertion) y Artifact (canal trasero para alto aseguramiento).
- La assertion lleva Subject, Conditions, AuthnStatement y AttributeStatement — y la seguridad del SP vive enteramente en validar todo ello.
- La firma da integridad y autenticidad (obligatoria); el cifrado da confidencialidad (opcional). La mayoría de las brechas SAML son fallos de validación, no fallos del protocolo.
- SAML todavía gana para SSO de plantilla empresarial, federación B2B y patrimonios con cumplimiento pesado; OAuth/OIDC ganan para consumidor, móvil y APIs.
Ejercicios prácticos
Estos son prácticos — hazlos, no solo los leas:
- Decodifica una assertion real. Instala una extensión de navegador SAML-tracer, inicia sesión en cualquier app protegida con SAML que uses, y captura el flujo. Encuentra el AuthnRequest y la assertion, decodifica la assertion de base64, y etiqueta su Subject, Conditions, AuthnStatement y AttributeStatement en el XML en vivo.
- Identifica los bindings. En esa misma captura, confirma qué binding llevó el AuthnRequest y cuál llevó la assertion. Verifica que coincide con el patrón “Redirect para la solicitud, POST para la assertion” — y nota el
NotOnOrAfterpara ver qué tan corta es realmente la vida de la assertion. - Levanta una federación. Usa un sandbox público como samltest.id para jugar ambos roles: registra un SP de prueba, sube metadata, y corre un login SP-initiated de extremo a extremo. Luego rómpelo a propósito — cambia la audiencia o deja un certificado que no coincide — y observa al SP rechazar la assertion.
- Audita una configuración (caso de uso). Heredas un SP que valida solo la firma de la respuesta externa y acepta assertions con una vida de 24 horas y sin AudienceRestriction. Lista cada problema y el cambio exacto para cada uno.
- Diseña un onboarding B2B (caso de uso). Una empresa socia necesita que sus empleados accedan a tu app vía su propio IdP. Esboza el intercambio de metadata, el formato de NameID que elegirías y por qué, los tres atributos que mapearías, y cómo manejarías la rotación de su certificado.
- Elige el protocolo (caso de uso). Toma una app que alcances vía SAML y revisa si también ofrece OIDC. Luego decide cuál elegirías para una app web interna nueva frente a una integración con un socio B2B, y justifica cada elección en dos frases usando la tabla comparativa de arriba.
Tres preguntas para autoevaluarte
- Un SP acepta una assertion SAML y lee los atributos de grupo del usuario para otorgar acceso de admin — pero solo verifica la firma de la respuesta externa, no la de la assertion misma. ¿Qué clase de ataque invita esto, y qué debería validar el SP en su lugar?
- Un colega habilita SSO IdP-initiated para una aplicación de finanzas porque la lanzadera de mosaicos de apps es cómoda. ¿Cuál es la objeción de seguridad, y qué recomendarías?
- Explica por qué SAML usa HTTP-Redirect para el AuthnRequest pero HTTP-POST para la assertion, y qué cambia HTTP-Artifact sobre dónde viaja la assertion.
Preguntas frecuentes
¿Qué es SAML 2.0?
SAML 2.0 (Security Assertion Markup Language) es un estándar de OASIS de 2005 para autenticación federada: permite que un proveedor de identidad responda por un usuario — con una 'assertion' XML firmada criptográficamente — para que pueda iniciar sesión en un proveedor de servicio sin que este vea jamás su contraseña. Es el protocolo que hizo posible el single sign-on web empresarial y sigue siendo ubicuo en SaaS corporativo y B2B.
¿Cuál es la diferencia entre un IdP y un SP en SAML?
El proveedor de identidad (IdP) es el sistema que autentica al usuario y emite la assertion — típicamente el login respaldado por el directorio de la empresa, como Entra ID, Okta o ADFS. El proveedor de servicio (SP) es la aplicación que el usuario quiere usar, que confía en la assertion del IdP en lugar de correr su propio login. El usuario (principal) se autentica una vez en el IdP y es admitido en muchos SPs.
¿Cuál es la diferencia entre SSO SP-initiated e IdP-initiated?
En el SSO SP-initiated el usuario empieza en la aplicación, que lo redirige al IdP para autenticarse y luego de vuelta con una assertion — el flujo más común y más seguro. En el SSO IdP-initiated el usuario empieza en un portal del IdP y hace clic en un mosaico de app, así que el IdP envía una assertion no solicitada al SP. El IdP-initiated es cómodo pero más expuesto a replay y se desaconseja para apps sensibles.
¿Qué es una SAML assertion?
Una SAML assertion es el documento XML firmado que el IdP emite para responder por un usuario. Contiene un Subject (quién es el usuario), Conditions (ventana de validez y para qué SP es la assertion), un AuthnStatement (cómo y cuándo se autenticó) y un AttributeStatement (atributos como correo, departamento o grupo). El SP valida la firma y las condiciones, y luego confía en su contenido para establecer una sesión.
¿En qué se diferencian la firma y el cifrado en SAML?
La firma (XML Signature) prueba que la assertion es auténtica e inalterada — el SP la verifica con el certificado público del IdP obtenido del metadata, y en la práctica es obligatoria. El cifrado (XML Encryption) oculta el contenido de la assertion de cualquiera salvo el SP destinatario y es opcional, usado cuando los atributos son sensibles. La firma protege integridad y autenticidad; el cifrado protege confidencialidad.
¿SAML sigue siendo relevante frente a OAuth y OIDC?
Sí, en su nicho. SAML sigue siendo el predeterminado para el SSO de plantilla empresarial y la federación B2B, donde los IdP maduros, los requisitos de cumplimiento profundos y el soporte existente de las apps lo vuelven el camino de menor resistencia. Para login de consumidor, apps móviles y autorización de APIs, los más ligeros OAuth 2.0 y OpenID Connect basados en JSON han ganado en gran medida — así que ambos coexisten, cada uno fuerte donde el otro es torpe.