OWASP & AppSec

SAML expliqué : SSO entreprise, flows, attaques, sécurité 2026

SAML 2.0 expliqué : SSO entreprise, SP-initiated vs IdP-initiated, structure assertion, XSW, Golden SAML, XXE, OIDC vs SAML et bonnes pratiques implémentation.

Naim Aouaichia
13 min de lecture
  • SAML
  • SSO
  • Authentification
  • XML
  • Identity
  • Enterprise
  • Secure coding
  • OWASP

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 OIDC

Ce 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 HTTP

Les 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ée

IdP-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éalable

Artifact 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émentRôleValidation obligatoire
<ds:Signature>Signature cryptographiqueOui - vérifier avec le certificat IdP connu
<saml:Issuer>Émetteur de l'assertionOui - matcher l'IdP configuré
<saml:Audience>Destinataire autoriséOui - doit contenir l'URL du SP
<saml:NotBefore> / <saml:NotOnOrAfter>Fenêtre temporelleOui - avec clock skew raisonnable
<saml:Destination>URL ACS attendueOui - matcher exactement
<saml:InResponseTo>ID SAMLRequest originalOui en SP-initiated
<saml:NameID>Identifiant utilisateurOui - c'est l'identité reçue
<saml:SessionIndex>ID session IdPUtile pour logout SLO

SAML vs OpenID Connect

Les deux coexistent en 2026. Voici les critères de choix.

CritèreSAML 2.0OpenID Connect
Année de ratification20052014
FormatXMLJSON / JWT
VerbositéTrès élevéeFaible
Support mobile natifLimitéExcellent
SPA / PWADifficileNatif
CI/CD Workload IdentityInexistantStandard 2026
SSO entreprise B2BDominant historiqueProgression rapide
Éducation (eduGAIN)DominantPeu adopté
Complexité d'implémentationÉlevéeMoyenne
Écosystème bibliothèquesMature mais vieillissantTrès actif
Rotation de clésManuelle fréquenteAutomatique via JWKS
Révocation de sessionSLO (Single Logout) complexeSession revocation + short tokens
Attaques historiquesXSW, Golden SAML, XXEalg: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 public

Pour 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 dynamiques

Golden 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 cloud

XXE (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 parser

RelayState 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 finale

Signature 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 populaire

Cô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 legacy

Bonnes pratiques 2026

  1. Utiliser exclusivement des bibliothèques SAML éprouvées - jamais d'implémentation maison.
  2. Signer l'Assertion (pas seulement la Response) et idéalement chiffrer avec EncryptedAssertion.
  3. Certificat de signature IdP vérifié côté SP - configuration manuelle, pas via KeyInfo reçu.
  4. Certificats distincts pour signature et chiffrement (recommandation OASIS).
  5. Algorithmes RSA-SHA256 minimum (bannir SHA1, MD5, RSA-1024).
  6. Validation stricte : Issuer, Audience, Destination, NotBefore, NotOnOrAfter, InResponseTo.
  7. RelayState whitelisté côté SP - pas d'URL arbitraire acceptée.
  8. Parseur XML durci : pas de DTD, pas de références externes, protection XXE.
  9. Rotation trimestrielle des certificats IdP + SP avec période de cohabitation.
  10. Logging détaillé des SAML Response reçus pour forensic (sans PII, avec ID et timestamp).
  11. Monitoring Golden SAML : corrélation logs IdP ↔ SP, alertes sur authN SP sans trace IdP.
  12. Single Logout (SLO) via LogoutRequest signé 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.

Questions fréquentes

  • Qu'est-ce que SAML exactement ?
    SAML (Security Assertion Markup Language) est un standard OASIS XML-based pour l'échange d'informations d'authentification et d'autorisation entre deux parties : l'Identity Provider (IdP) qui authentifie l'utilisateur, et le Service Provider (SP) qui consomme l'assertion. SAML 2.0 finalisé en 2005 est la version dominante en 2026. Usage principal : SSO entreprise - un utilisateur se connecte une fois chez l'IdP (Entra ID, Okta, Ping, ADFS) et accède ensuite à des dizaines d'applications SP sans re-saisir ses credentials.
  • Quelle différence entre SAML et OpenID Connect (OIDC) ?
    SAML est XML-based, verbose, historique du SSO enterprise (ADFS, Ping, Shibboleth), omniprésent dans les SaaS B2B et l'éducation. OIDC est JSON/JWT-based, moderne, adopté par mobile et web 2.0+. En 2026, les deux coexistent. Nouveaux déploiements : OIDC de préférence (plus simple, mobile-friendly, écosystème CI/CD). Intégrations B2B enterprise : SAML reste souvent imposé par le client (SOC 2 et ISO 27001 audits attendent SAML SSO). Les IdP modernes (Entra, Okta, Auth0) supportent les deux en parallèle.
  • Qu'est-ce qu'une attaque XML Signature Wrapping ?
    Aussi connue sous XSW, c'est la vulnérabilité SAML la plus infâme. L'attaquant insère une assertion forgée dans un SAML Response signé légitime, en exploitant la flexibilité de XML Signature qui signe une référence à un élément par ID, pas son contenu contextuel. Le SP valide la signature sur l'élément original mais consomme l'élément forgé. Popularisé par Somorovsky et al. 2012. Toujours présent en 2024-2025 dans des implémentations maison. Parade : utiliser uniquement des bibliothèques SAML éprouvées (pysaml2, saml-toolkit, Shibboleth SP) qui valident l'ID référencé exactement.
  • Qu'est-ce que Golden SAML ?
    Attaque documentée par CyberArk en 2017 et utilisée par APT29 dans SolarWinds (2020). Un attaquant qui compromet la clé privée de signature de l'IdP peut forger des SAML Assertions valides pour n'importe quel utilisateur, de manière indétectable côté SP. Parades : stockage de la clé IdP en HSM ou Azure Key Vault, rotation régulière, monitoring strict de tout accès à la clé, limitations d'audience (conditions Audience Restriction), et corrélation de logs IdP ↔ SP pour détecter des authentifications sans trace correspondante chez l'IdP.
  • Quels pièges SAML les développeurs rencontrent le plus souvent ?
    Cinq pièges classiques. 1) Implémenter le parseur XML from scratch (XXE, billion laughs, XSW garantis). 2) Ne pas valider InResponseTo et In-Reply-To (vulnérable CSRF cross-session). 3) Ne pas chiffrer les assertions (SAML Response en clair sur le canal retour si pas de TLS pinning). 4) Accepter RelayState sans whitelisting (open redirect). 5) Confondre authentification et autorisation : SAML dit qui mais pas quoi - l'application doit toujours gérer les rôles et permissions séparément.
  • SAML est-il encore pertinent en 2026 ?
    Oui, massivement. SAML domine le SSO B2B enterprise où il est souvent exigé contractuellement. La quasi-totalité des SaaS B2B proposent SAML SSO dans leur plan enterprise (Slack Enterprise Grid, Salesforce, Workday, ServiceNow, Zoom, Atlassian, GitHub Enterprise). Le secteur éducation utilise Shibboleth SAML massivement. Les gouvernements européens privilégient souvent SAML via eduGAIN, FranceConnect utilise OIDC+SAML. OIDC progresse sur le nouveau développement mais SAML reste incontournable pour toute intégration B2B mature.

Écrit par

Naim Aouaichia

Expert cybersécurité et fondateur de Zeroday Cyber Academy

Expert cybersécurité avec un master spécialisé et un parcours hybride : développement, DevOps, DevSecOps, SOC, GRC. Fondateur de Hash24Security et Zeroday Cyber Academy. Formateur et créateur de contenu technique sur la cybersécurité appliquée, la sécurité des LLM et le DevSecOps.