Aller au contenu
medium

SAML 2.0 : la fédération enterprise

11 min de lecture

SAML 2.0 reste le protocole de fédération dominant en entreprise. Même si OIDC est plus moderne, la majorité des applications SaaS enterprise (Salesforce, ServiceNow, Workday…) supportent SAML en premier. Si vous intégrez des applications d’entreprise, vous rencontrerez SAML. Ce guide vous donne les clés pour le comprendre, le configurer et le déboguer.

Ce guide vous explique SAML 2.0 — le protocole de fédération dominant dans les grandes entreprises. À la fin, vous saurez :

  • Comprendre pourquoi SAML reste omniprésent malgré OIDC
  • Distinguer les flux SP-initiated et IdP-initiated
  • Configurer les assertions, signatures et mapping d’attributs
  • Diagnostiquer les erreurs SAML les plus courantes

Prérequis : avoir lu OpenID Connect.

SAML 2.0 date de 2005. Pourquoi est-il encore partout ?

Réponse courte : parce que les grandes applications enterprise (Salesforce, ServiceNow, Workday, SAP…) le supportent depuis des années, et qu’il fonctionne.

SituationProtocole recommandé
L’application ne supporte que SAMLSAML
Intégration B2B avec un partenaire SAMLSAML
Nouvelle application web/mobileOIDC
API à sécuriserOAuth 2.0

Comprendre ces différences vous aide à choisir le bon protocole selon votre contexte. SAML reste incontournable en entreprise, tandis qu’OIDC domine les architectures modernes.

AspectSAMLOIDC
Année20052014
FormatXMLJSON/JWT
Taille des messagesVerbeux (~5-15 KB)Compact (~1-2 KB)
SignatureXML-DSig + certificatsJWS (signature JWT)
ChiffrementXML-Enc (optionnel)JWE (optionnel)
ConfigurationÉchange de fichiers metadataDiscovery endpoint
Mobile/SPADifficileNatif
Enterprise legacyExcellent supportVariable
DebuggingComplexe (XML, signatures)Simple (jwt.io, JSON)

Trois acteurs interviennent dans chaque échange SAML. Connaître leur rôle est essentiel pour déboguer les problèmes de fédération.

ActeurRôleÉquivalent OIDC
Identity Provider (IdP)Authentifie l’utilisateur, émet les assertionsOpenID Provider
Service Provider (SP)Application qui consomme les assertionsRelying Party
PrincipalL’utilisateur qui s’authentifie

L’utilisateur commence par l’application (Service Provider).

  1. Accès à l’application

    L’utilisateur tente d’accéder à https://salesforce.example.com

  2. Génération de l’AuthnRequest

    Le SP génère une demande d’authentification SAML (AuthnRequest).

  3. Redirection vers l’IdP

    Le navigateur est redirigé vers l’IdP avec l’AuthnRequest.

  4. Authentification

    L’IdP authentifie l’utilisateur (login, MFA…).

  5. Génération de l’assertion

    L’IdP crée une assertion SAML signée contenant l’identité.

  6. Retour au SP (POST)

    Le navigateur envoie l’assertion au SP (généralement via HTTP-POST).

  7. Validation et session

    Le SP valide la signature et crée une session pour l’utilisateur.

Avantages :

  • L’application contrôle le flux
  • Protection CSRF native (le SP génère un ID de requête)

L’utilisateur commence par le portail IdP.

  1. Accès au portail IdP

    L’utilisateur accède au portail enterprise (ex: Okta dashboard).

  2. Clic sur l’application

    L’utilisateur clique sur l’icône de l’application.

  3. Génération directe de l’assertion

    L’IdP génère une assertion SAML sans AuthnRequest préalable.

  4. Envoi au SP

    L’assertion est envoyée directement au SP.

  5. Validation et session

    Le SP valide et crée la session.

Risques :

  • Pas d’AuthnRequest = pas de InResponseTo à valider
  • Risque de CSRF si le RelayState n’est pas vérifié

Une assertion SAML est un document XML signé qui contient :

  • L’identité de l’utilisateur (NameID)
  • Les attributs (email, groupes, rôles…)
  • Les conditions de validité (dates, audience)
  • La signature de l’IdP
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_abc123" IssueInstant="2024-02-06T10:00:00Z">
<!-- Qui a émis l'assertion -->
<saml:Issuer>https://idp.example.com</saml:Issuer>
<!-- Signature XML -->
<ds:Signature>...</ds:Signature>
<!-- Subject : l'utilisateur authentifié -->
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
alice@example.com
</saml:NameID>
</saml:Subject>
<!-- Conditions de validité -->
<saml:Conditions NotBefore="2024-02-06T10:00:00Z"
NotOnOrAfter="2024-02-06T10:05:00Z">
<saml:AudienceRestriction>
<saml:Audience>https://salesforce.example.com</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<!-- Contexte d'authentification -->
<saml:AuthnStatement AuthnInstant="2024-02-06T10:00:00Z">
<saml:AuthnContext>
<saml:AuthnContextClassRef>
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<!-- Attributs -->
<saml:AttributeStatement>
<saml:Attribute Name="email">
<saml:AttributeValue>alice@example.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="groups">
<saml:AttributeValue>developers</saml:AttributeValue>
<saml:AttributeValue>admins</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
ÉlémentDescription
IssuerURL de l’IdP qui a émis l’assertion
NameIDIdentifiant principal de l’utilisateur
ConditionsPériode de validité, audience autorisée
AuthnStatementPreuve de l’authentification
AttributeStatementAttributs additionnels (email, groupes…)
SignatureSignature XML de l’IdP

SAML utilise XML-DSig pour signer les assertions (et optionnellement les chiffrer).

ÉlémentSigné par
AssertionL’IdP (obligatoire)
ResponseL’IdP (recommandé)
AuthnRequestLe SP (optionnel)

Le SP doit :

  1. Obtenir le certificat public de l’IdP (via metadata ou import manuel)
  2. Valider la signature de l’assertion
  3. Valider la chaîne de certificats (optionnel selon la config)

Les fichiers metadata contiennent la configuration SAML d’un IdP ou d’un SP.

<EntityDescriptor entityID="https://idp.example.com">
<IDPSSODescriptor>
<KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIC...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</KeyDescriptor>
<SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="https://idp.example.com/sso"/>
</IDPSSODescriptor>
</EntityDescriptor>
<EntityDescriptor entityID="https://salesforce.example.com">
<SPSSODescriptor>
<KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIID...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</KeyDescriptor>
<AssertionConsumerService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://salesforce.example.com/saml/acs"
index="0"/>
</SPSSODescriptor>
</EntityDescriptor>
  1. Exporter le metadata de l’IdP

  2. Importer dans le SP (ou donner l’URL du metadata)

  3. Exporter le metadata du SP

  4. Importer dans l’IdP (créer un “realm” ou “application”)

  5. Configurer le mapping d’attributs

Les attributs SAML ne sont pas standardisés. Chaque vendor utilise ses propres noms.

FormatValeurUsage
emailAddressalice@example.comLe plus courant
persistentID opaque stableRecommandé pour la sécurité
transientID temporaireSessions anonymes
unspecifiedQuelconqueÀ éviter
Ce que le SP attendCe que l’IdP aSolution
User.EmailemailMapper emailUser.Email
memberOfgroupsMapper groupsmemberOf
firstNamegivenNameMapper givenNamefirstName
OutilUsage
SAML-tracer (extension navigateur)Capturer les requêtes/réponses SAML
samltool.comDécoder, valider, générer des assertions
Keycloak logsErreurs côté IdP
Logs applicatifsErreurs côté SP
SymptômeCause probableSolution
Invalid signatureCertificat mal importé, mauvais certificatRé-importer le certificat de l’IdP
Assertion expiredClock skew (décalage d’horloge)Synchroniser NTP sur tous les serveurs
Invalid audienceAudience ne correspond pas à l’entityID du SPVérifier la config côté IdP
ACS URL mismatchL’URL de retour ne correspond pasVérifier AssertionConsumerService dans les metadata
Missing attributeAttribut non mappéConfigurer le mapper côté IdP
NameID format mismatchLe SP attend un format différentAligner les formats NameID
  1. Capturer le trafic avec SAML-tracer

  2. Décoder la Response sur samltool.com

  3. Vérifier les timestamps (NotBefore, NotOnOrAfter)

  4. Vérifier l’Audience

  5. Valider la signature (certificat correct ?)

  6. Vérifier les attributs présents dans l’assertion

RisqueMitigation
Signature bypassToujours valider la signature de l’assertion ET de la response
XML injectionParser XML sécurisé, désactiver les entity references
Replay attackVérifier InResponseTo, tracker les assertion IDs consommées
IdP-initiated CSRFValider RelayState, préférer SP-initiated
Assertion interceptionHTTPS obligatoire, chiffrement optionnel
  • Signez les assertions ET les responses
  • Chiffrez les assertions si elles contiennent des données sensibles
  • Validez l’audience (AudienceRestriction)
  • Limitez la durée de validité des assertions (< 5 min)
  • Utilisez SP-initiated quand possible
ErreurConséquenceSolution
Certificat expiré non détectéSSO casséAlerting sur les dates d’expiration
Pas de validation InResponseToVulnérable au replayValider l’ID de la requête originale
Clock skew > 5 minAssertions toujours rejetéesNTP sur tous les serveurs
Metadata pas à jourÉchecs intermittentsURL de metadata + refresh automatique

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.