Comment décoder un message SAML
- Collez ce que vous avez. Tout ceci fonctionne :
- la valeur
SAMLResponseouSAMLRequestseule, encodée en URL ou non SAMLRequest=…avec ou sansRelayState,SigAlgetSignature- une URL Redirect complète copiée depuis la barre d’adresse
- le formulaire HTML à envoi automatique avec le champ caché
SAMLResponse - du XML brut
- la valeur
- Le décodeur détecte le binding : du Base64 simple signifie HTTP-POST, des données compressées en deflate signifient HTTP-Redirect.
- Lisez d’abord le résumé, puis le XML formaté en dessous. Le XML est affiché comme du texte et n’est jamais interprété.
Le sens Encoder fait l’inverse : collez un AuthnRequest et obtenez une valeur Redirect, un paramètre SAMLRequest= ou une URL complète construite à partir de l’attribut Destination. C’est pratique pour rejouer une requête pendant les tests d’un fournisseur de services.
Binding Redirect ou binding POST
| HTTP-Redirect | HTTP-POST | |
|---|---|---|
| Transport | Query string d’une requête GET | Champ de formulaire caché, envoyé automatiquement |
| Encodage | raw DEFLATE, puis Base64, puis encodage URL | Base64 seul |
| Message typique | AuthnRequest, LogoutRequest | Response avec assertions |
| Signature | Paramètres SigAlg et Signature séparés | Signature XML dans le message |
| Reconnaissable à | aucun préfixe fixe, binaire après Base64 | PHNhbWxwOl (<samlp:), PHNhbWwycDp (<saml2p:), PD94bWwg (<?xml ) |
Le binding Redirect compresse parce que les URL ont des limites de longueur en pratique. Dans l’exemple utilisé sur cette page, un AuthnRequest de 464 caractères se compresse en 273 octets et voyage sous forme de 364 caractères Base64. Les réponses transportent des signatures et des certificats : elles sont trop grosses pour une URL et passent par POST. Le décodeur accepte aussi les données avec en-tête zlib, que certains fournisseurs de services envoient en Redirect à la place du raw deflate.
Que vérifier quand le SSO échoue
Le résumé met en avant les champs responsables de la plupart des échecs de connexion :
- Status : tout ce qui n’est pas
urn:oasis:names:tc:SAML:2.0:status:Success. Un sous-code commeAuthnFailed,InvalidNameIDPolicyouRequestDeniedindique la raison, etStatusMessageajoute souvent des détails. - Destination et URL ACS : doivent correspondre exactement au point de terminaison configuré chez le fournisseur de services,
httpset barre oblique finale compris. - Audience : doit être égale à l’entity ID du SP. Un écart ici est une erreur de configuration fréquente après le renommage d’une application.
- Conditions :
NotBeforeetNotOnOrAftersont comparés à votre horloge. « Expirées » ou « pas encore valides » sur une connexion toute fraîche indique un décalage d’horloge entre l’IdP et le SP. - InResponseTo : doit être égal à l’
IDde l’AuthnRequest. Un écart évoque une réponse périmée ou rejouée. L’attribut est absent des connexions initiées par l’IdP, que certains fournisseurs de services refusent. - NameID et Format : l’identifiant que le SP va comparer à ses utilisateurs, par exemple
emailAddressoupersistent. - Attributs : chaque attribut avec toutes ses valeurs, pour confirmer que l’IdP envoie bien les groupes ou l’e-mail que le SP attend.
Décoder du SAML en Python
import base64, zlib
from urllib.parse import unquote
def decode_post(value):
return base64.b64decode(value).decode()
def decode_redirect(value):
raw = base64.b64decode(unquote(value))
return zlib.decompress(raw, -15).decode()
Le -15 indique à zlib d’attendre du raw deflate sans en-tête. N’appelez unquote que sur des valeurs copiées depuis une URL : une valeur issue d’un formulaire POST est déjà du Base64 simple, et la décoder comme une URL peut transformer + en espace. Plus de détails dans Base64 en Python ; la compression est expliquée sur la page raw deflate et zlib.
Confidentialité des assertions SAML
Une assertion contient des noms, des adresses e-mail, des appartenances à des groupes et parfois d’autres données personnelles, et une assertion valide non expirée peut servir de jeton de connexion. Cette page la décode localement et ne peut l’envoyer nulle part. Masquez tout de même les assertions avant de les coller dans un ticket ou une discussion, et traitez une réponse capturée comme un cookie de session tant que son NotOnOrAfter n’est pas dépassé.
FAQ
Comment capturer une réponse SAML dans le navigateur ?
Ouvrez les outils de développement, activez Conserver le journal (Preserve log) dans l’onglet Réseau et connectez-vous. Repérez la requête POST vers l’URL ACS du fournisseur de services et copiez le champ de formulaire SAMLResponse de son payload. Collez-le ici.
Pourquoi mon SAMLRequest ne se décode-t-il pas avec un décodeur Base64 classique ?
Avec le binding HTTP-Redirect, le XML est compressé en raw deflate avant l’encodage Base64 et l’encodage URL. Un décodeur simple n’affiche que du bruit binaire. Cet outil fait le décodage URL, le décodage Base64 et la décompression en une seule fois.
Le décodeur vérifie-t-il la signature SAML ?
Non. Il indique si le message, l’assertion ou la query string est signé, mais il ne vérifie pas la signature avec le certificat de l’IdP. La validation de la signature relève du fournisseur de services.
Peut-il déchiffrer une EncryptedAssertion ?
Non. Les assertions chiffrées nécessitent la clé privée du fournisseur de services. Le décodeur les compte et affiche quand même l’enveloppe non chiffrée : statut, émetteur et destination.