SAML (Security Assertion Markup Language) est un standard OASIS ratifié en version 2.0 en mars 2005 pour l'échange d'informations d'authentification et d'autorisation au format XML entre deux parties : un Identity Provider (IdP) qui authentifie l'utilisateur, et un Service Provider (SP) qui consomme l'assertion signée. C'est le protocole historique du Single Sign-On enterprise : un utilisateur se connecte une fois chez son IdP (Entra ID, Okta, Ping Federate, ADFS, Shibboleth, Keycloak) et accède ensuite à des dizaines d'applications SaaS sans re-saisir ses credentials. En 2026, SAML reste dominant en B2B enterprise (SaaS premium exigent SAML SSO en plan entreprise), éducation (via Shibboleth et eduGAIN) et secteur public européen, alors que OpenID Connect (OIDC) le remplace progressivement pour les nouveaux développements mobile et API-first. SAML est également connu pour ses vulnérabilités classiques - XML Signature Wrapping (XSW), Golden SAML (SolarWinds 2020), XXE, RelayState open redirect - qui exigent rigueur d'implémentation et usage de bibliothèques éprouvées. Cet article détaille la définition, les flows SP-initiated vs IdP-initiated, la structure d'une assertion, les attaques documentées et les bonnes pratiques 2026.
Définition et genèse
SAML a été standardisé par OASIS (Organization for the Advancement of Structured Information Standards) pour adresser le besoin de Single Sign-On cross-domain en entreprise.
Chronologie SAML :
2002 SAML 1.0 : premier standard, peu adopté
2003 SAML 1.1 : clarifications
2005 SAML 2.0 : version de référence, dominante depuis
2012 Publications académiques sur XSW (Somorovsky et al.)
2017 CyberArk publie le research Golden SAML
2020 APT29 (Nobelium) exploite Golden SAML dans SolarWinds
2024 Toujours dominant en B2B enterprise malgré concurrence OIDCCe que SAML apporte
- SSO cross-domain : login unique chez l'IdP, accès à plusieurs SP.
- Assertions signées cryptographiquement : le SP peut vérifier l'identité sans contacter l'IdP à chaque requête.
- Attribute exchange : l'IdP peut transmettre des attributs utilisateur (email, groupes, département) au SP dans l'assertion.
- Federation : plusieurs IdP peuvent fédérer (eduGAIN avec 4 000+ institutions).
Les 3 rôles SAML
Identity Provider (IdP)
Authentifie l'utilisateur et émet les assertions signées
Exemples : Microsoft Entra ID, Okta, Ping Federate,
ADFS (Active Directory Federation Services),
Shibboleth (éducation), Keycloak, SimpleSAMLphp
Service Provider (SP)
Consomme l'assertion pour donner accès à l'utilisateur
Exemples : Salesforce, Slack, GitHub, Workday, ServiceNow,
vos applications internes exposées en SaaS
User Agent (User)
Le navigateur de l'utilisateur final qui transporte les messages
entre IdP et SP via redirections HTTPLes 2 flows principaux
SP-initiated SAML flow (le plus courant)
L'utilisateur essaie d'accéder à une ressource SP sans session active. Le SP le redirige vers l'IdP pour authentification, puis l'IdP renvoie l'assertion vers le SP.
1. User → GET https://sp.example/protected
(pas de session active)
2. SP → 302 Redirect vers IdP
avec SAMLRequest encodé dans le query parameter
https://idp.example/sso?SAMLRequest=<base64>&RelayState=<url_retour>
3. IdP authentifie l'utilisateur (login + MFA si requis)
4. IdP → POST vers SP callback avec SAML Response signée
<form action="https://sp.example/acs" method="POST">
<input name="SAMLResponse" value="<base64_xml_signed>"/>
<input name="RelayState" value="<url_retour>"/>
</form>
(auto-submit JavaScript ou META refresh)
5. SP valide la signature, vérifie conditions, ouvre session
Redirige vers RelayState ou ressource initialement demandéeIdP-initiated SAML flow
L'utilisateur démarre depuis un portail IdP (portail d'apps enterprise Okta, MyApps Entra ID) et clique sur une tuile SP.
1. User se connecte sur son portail IdP
2. User clique sur une tuile (ex. Slack)
3. IdP génère directement une SAML Response signée pour SP
4. POST vers SP Assertion Consumer Service (ACS)
5. SP valide et ouvre session sans SAMLRequest préalableArtifact Binding (rarement utilisé)
Alternative au POST Binding où l'IdP envoie un artifact (référence courte) au SP, qui la récupère en back-channel SOAP auprès de l'IdP. Plus sûr théoriquement (pas d'exposition de l'assertion dans le navigateur) mais complexe et peu supporté.
Structure d'une SAML Assertion (XML)
<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_abc123def456"
Version="2.0"
IssueInstant="2026-04-24T09:14:32Z"
Destination="https://sp.example/acs"
InResponseTo="_originalRequestID">
<saml:Issuer>https://idp.example</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion ID="_assert789" Version="2.0"
IssueInstant="2026-04-24T09:14:32Z">
<saml:Issuer>https://idp.example</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#_assert789">
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>...</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>...</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIC...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
alice@example.com
</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2026-04-24T09:19:32Z"
Recipient="https://sp.example/acs"
InResponseTo="_originalRequestID"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2026-04-24T09:14:32Z"
NotOnOrAfter="2026-04-24T09:19:32Z">
<saml:AudienceRestriction>
<saml:Audience>https://sp.example</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2026-04-24T09:14:30Z"
SessionIndex="_session456">
<saml:AuthnContext>
<saml:AuthnContextClassRef>
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="email">
<saml:AttributeValue>alice@example.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="groups">
<saml:AttributeValue>admins</saml:AttributeValue>
<saml:AttributeValue>engineers</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>Éléments critiques à valider
| Élément | Rôle | Validation obligatoire |
|---|---|---|
<ds:Signature> | Signature cryptographique | Oui - vérifier avec le certificat IdP connu |
<saml:Issuer> | Émetteur de l'assertion | Oui - matcher l'IdP configuré |
<saml:Audience> | Destinataire autorisé | Oui - doit contenir l'URL du SP |
<saml:NotBefore> / <saml:NotOnOrAfter> | Fenêtre temporelle | Oui - avec clock skew raisonnable |
<saml:Destination> | URL ACS attendue | Oui - matcher exactement |
<saml:InResponseTo> | ID SAMLRequest original | Oui en SP-initiated |
<saml:NameID> | Identifiant utilisateur | Oui - c'est l'identité reçue |
<saml:SessionIndex> | ID session IdP | Utile pour logout SLO |
SAML vs OpenID Connect
Les deux coexistent en 2026. Voici les critères de choix.
| Critère | SAML 2.0 | OpenID Connect |
|---|---|---|
| Année de ratification | 2005 | 2014 |
| Format | XML | JSON / JWT |
| Verbosité | Très élevée | Faible |
| Support mobile natif | Limité | Excellent |
| SPA / PWA | Difficile | Natif |
| CI/CD Workload Identity | Inexistant | Standard 2026 |
| SSO entreprise B2B | Dominant historique | Progression rapide |
| Éducation (eduGAIN) | Dominant | Peu adopté |
| Complexité d'implémentation | Élevée | Moyenne |
| Écosystème bibliothèques | Mature mais vieillissant | Très actif |
| Rotation de clés | Manuelle fréquente | Automatique via JWKS |
| Révocation de session | SLO (Single Logout) complexe | Session revocation + short tokens |
| Attaques historiques | XSW, Golden SAML, XXE | alg:none, SSRF, confusion algo |
Quand choisir SAML en 2026
Intégration obligatoire :
Client enterprise B2B qui exige SAML SSO (SOC 2, ISO 27001)
Secteur public européen qui déploie via Shibboleth
Fédération académique (eduGAIN)
Applications legacy sans support OIDC
Migration recommandée vers OIDC :
Nouveaux développements mobile et SPA
Architecture API-first
CI/CD avec Workload Identity Federation
Produits destinés au grand publicPour une vue détaillée OIDC, voir OpenID Connect expliqué : flows, JWT, PKCE, sécurité 2026.
Attaques courantes et parades
XML Signature Wrapping (XSW)
La vulnérabilité SAML la plus célèbre, documentée par Somorovsky et al. en 2012.
Principe :
XML Signature signe une référence à un élément via son ID (Reference URI).
Si le parseur SAML cherche l'élément par nom ou position plutôt que
strictement par l'ID référencé dans la signature, un attaquant peut
insérer une nouvelle assertion forgée (avec un ID différent) dans
l'arbre XML tout en conservant l'assertion signée originale.
Le validateur voit une signature valide sur l'ancienne assertion,
mais le consommateur applicatif lit la nouvelle assertion injectée.
Parades :
- Utiliser une bibliothèque SAML éprouvée (pysaml2, python3-saml,
saml-toolkit, OneLogin, Shibboleth SP, SimpleSAMLphp)
- Ne jamais écrire son propre parseur SAML
- Valider que l'élément consommé est bien celui dont l'ID est signé
- Désactiver les évaluations XPath dynamiquesGolden SAML
Attaque documentée par CyberArk en 2017, utilisée par Nobelium (APT29) dans SolarWinds (décembre 2020).
Principe :
L'attaquant compromet la clé privée de signature de l'IdP (ADFS
typiquement). Avec cette clé, il peut forger des SAML Assertions
valides pour n'importe quel utilisateur, vers n'importe quel SP
qui fait confiance à cet IdP.
L'attaque est quasi indétectable car :
- La signature est cryptographiquement valide
- Le SP n'a aucun moyen de savoir si l'authentification a réellement eu lieu chez l'IdP
- Les logs IdP ne contiennent pas l'événement (assertion forgée hors IdP)
Parades :
- Stocker la clé privée IdP en HSM ou Azure Key Vault avec audit
- Rotation régulière (trimestrielle)
- Corrélation logs IdP ↔ SP : alerter sur authN SP sans trace IdP
- Monitoring accès à la clé (access audit)
- Use Azure Conditional Access pour bloquer les sessions suspectes
- Migrer vers Entra ID avec tokens court-durée et protection MFA cloudXXE (XML External Entity)
SAML étant XML-based, tout parseur mal configuré est vulnérable à XXE.
Payload XXE classique dans un SAMLResponse :
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<samlp:Response>
...
<saml:AttributeValue>&xxe;</saml:AttributeValue>
...
</samlp:Response>
Impact : lecture de fichiers locaux, SSRF, déni de service billion laughs
Parade :
- Désactiver les DTD dans le parseur XML (defusedxml en Python,
DOCUMENT_BUILDER_FACTORY configuré en Java)
- Ne jamais utiliser xml.etree.ElementTree sur du SAML user-controlled
sans protection
- Utiliser defusedxml, lxml avec secure parserRelayState open redirect
Le paramètre RelayState est conçu pour porter l'URL de retour après authentification. Sans whitelisting, un attaquant peut l'utiliser comme vecteur d'open redirect ou XSS.
Parade :
- Whitelister strict des URLs acceptées dans RelayState (même origine)
- Refuser les protocoles autres que https
- Valider côté SP avant redirection finaleSignature exclusion attack
Certaines implémentations acceptent une SAML Response sans signature (ou avec signature sur le wrapping Response mais pas sur l'Assertion).
Parade :
- Refuser toute assertion non signée
- Signer l'Assertion (pas seulement la Response)
- Chiffrer l'Assertion en plus (EncryptedAssertion)
- Valider que l'algorithme est RSA-SHA256 minimum (pas SHA1)Algorithm downgrade
Forcer l'utilisation d'algorithmes faibles (SHA1, RSA-1024).
Parade :
- Whitelister les algorithmes acceptés (RSA-SHA256, RSA-SHA384, RSA-SHA512)
- Bannir SHA1, MD5, RSA-1024
- Vérifier la taille minimale des clés (RSA 2048+, ECDSA 256+)Bibliothèques SAML 2026
Côté SP (implémentation service provider)
Python :
python3-saml (OneLogin) : référence, maintenu
pysaml2 : mature, SAML 2.0 complet
djangosaml2 : intégration Django
PHP :
SimpleSAMLphp : SP et IdP, open source
LightSAML : SP, moderne
Java :
Spring Security SAML2 : intégration Spring
OpenSAML : bibliothèque bas niveau (Shibboleth)
Keycloak Adapters : pour SP avec Keycloak comme IdP
Node.js :
@node-saml/node-saml : actif, maintenu
passport-saml : intégration Passport.js
Ruby :
ruby-saml (OneLogin) : référence
omniauth-saml : intégration Omniauth
Go :
crewjam/saml : SP et IdP
gosaml2 (Mattermost) : actif
.NET :
ITfoxtec.Identity.Saml2 : moderne, maintenu
Sustainsys.Saml2 : open source populaireCôté IdP
Keycloak (Red Hat OSS) : IdP polyvalent SAML + OIDC
SimpleSAMLphp (OSS) : IdP et SP simples
Shibboleth IdP (OSS) : éducation, eduGAIN
WSO2 Identity Server (OSS) : enterprise
Gluu Server (OSS + commercial) : scalable
Ory Hydra : OIDC only (pas SAML)
Zitadel : SAML + OIDC
Commercial :
Microsoft Entra ID : SAML + OIDC, dominant
Okta Workforce Identity : leader SaaS
Ping Federate : enterprise historique
OneLogin (One Identity) : SaaS
Auth0 (Okta) : développeur-friendly
ADFS (Microsoft) : on-premise legacyBonnes pratiques 2026
- Utiliser exclusivement des bibliothèques SAML éprouvées - jamais d'implémentation maison.
- Signer l'Assertion (pas seulement la Response) et idéalement chiffrer avec
EncryptedAssertion. - Certificat de signature IdP vérifié côté SP - configuration manuelle, pas via
KeyInforeçu. - Certificats distincts pour signature et chiffrement (recommandation OASIS).
- Algorithmes RSA-SHA256 minimum (bannir SHA1, MD5, RSA-1024).
- Validation stricte :
Issuer,Audience,Destination,NotBefore,NotOnOrAfter,InResponseTo. - RelayState whitelisté côté SP - pas d'URL arbitraire acceptée.
- Parseur XML durci : pas de DTD, pas de références externes, protection XXE.
- Rotation trimestrielle des certificats IdP + SP avec période de cohabitation.
- Logging détaillé des SAML Response reçus pour forensic (sans PII, avec ID et timestamp).
- Monitoring Golden SAML : corrélation logs IdP ↔ SP, alertes sur authN SP sans trace IdP.
- Single Logout (SLO) via
LogoutRequestsigné pour déconnecter l'utilisateur sur tous les SP.
Migration SAML → OIDC : quand et comment
Pour les organisations qui veulent migrer progressivement :
Approche hybride recommandée :
Mois 1-3 : Audit
Identifier toutes les applications SAML (souvent 50-200 dans une ETI)
Classifier par usage (B2B vs interne, mobile vs web, criticité)
Mois 3-12 : Migration nouvelles apps uniquement
Nouvelles apps : OIDC par défaut
Apps B2B : garder SAML si client l'exige
Ajouter OIDC en parallèle sur IdP (Entra et Okta supportent les deux)
Mois 12+ : Retrait progressif SAML
Mobile apps en priorité (OIDC beaucoup plus adapté)
Conserver SAML uniquement pour apps enterprise B2B qui l'exigent
Jamais d'urgence : SAML reste viable et sécurisé bien implémentéPoints clés à retenir
- SAML 2.0 (ratifié OASIS 2005) est le protocole SSO enterprise historique basé sur XML. Toujours dominant en B2B, éducation (eduGAIN) et secteur public européen en 2026.
- 3 rôles : IdP (Entra ID, Okta, Ping, ADFS, Keycloak) authentifie, SP (Salesforce, Slack, GitHub) consomme, User transporte via navigateur.
- 2 flows : SP-initiated (recommandé, protection InResponseTo) et IdP-initiated (depuis portail apps, moins sûr).
- Structure assertion XML avec signature XMLDSig, claims (NameID, Attributes), conditions (NotBefore, Audience), AuthnStatement.
- SAML vs OIDC 2026 : SAML domine B2B enterprise, OIDC domine mobile/API/SPA/CI-CD. Les deux coexistent, convergence OIDC progressive.
- 6 attaques documentées : XSW (Somorovsky 2012, toujours actuel), Golden SAML (CyberArk 2017, SolarWinds 2020), XXE, RelayState open redirect, signature exclusion, algorithm downgrade.
- Bonnes pratiques 2026 : bibliothèque éprouvée obligatoire, Assertion signée + chiffrée, RSA-SHA256 minimum, parseur XML durci, rotation trimestrielle, monitoring Golden SAML (corrélation IdP ↔ SP).
- Bibliothèques : python3-saml, pysaml2 (Python) ; Spring Security SAML2, OpenSAML (Java) ; node-saml (Node) ; ruby-saml (Ruby) ; crewjam/saml (Go). IdP : Entra ID, Okta, Keycloak, Shibboleth.
Pour approfondir l'alternative moderne avec JWT et mobile-friendly, voir OpenID Connect expliqué : flows, JWT, PKCE, sécurité 2026. Pour sécuriser l'autorisation qui s'exécute après authentification SAML (A01 OWASP), lire Broken Access Control : explication, exemples et prévention. Pour valider correctement les inputs SAML reçus (RelayState, SAMLResponse), voir Validation des entrées : bonnes pratiques secure coding 2026.





