Question Consommez le jeton SAMLResponse


L'authentification basée sur SAML a suivi un court flux de travail.

  • L'utilisateur veut accéder à l'application à sp.
  • sp envoie le jeton SAMLRequest à idp.
  • IDP le consomme et génère un jeton SAMLResponse.
  • IDP envoie ce jeton SAMLResponse à AC-URL donné par sp.

Ma question est de savoir comment sp consomme ce jeton SAMLResponse. Quelle est la logique? Si je peux obtenir de l'aide sur du code JAVA, cela sera bénéfique.


10
2017-07-13 15:07


origine


Réponses:


La prochaine recette travaille pour moi:

  1. Obtenez le jeton SAMLResponse et décodez-le et gonflez:

    // Base64 decode
    Base64 base64Decoder = new Base64();
    byte[] xmlBytes = encodedXmlString.getBytes("UTF-8");
    byte[] base64DecodedByteArray = base64Decoder.decode(xmlBytes);
    
    // Inflate (uncompress) the AuthnRequest data
    // First attempt to unzip the byte array according to DEFLATE (rfc 1951)
    
    Inflater inflater = new Inflater(true);
    inflater.setInput(base64DecodedByteArray);
    // since we are decompressing, it's impossible to know how much space we
    // might need; hopefully this number is suitably big
    byte[] xmlMessageBytes = new byte[5000];
    int resultLength = inflater.inflate(xmlMessageBytes);
    
    if (!inflater.finished()) {
        throw new RuntimeException("didn't allocate enough space to hold "
                + "decompressed data");
    }
    
    inflater.end();
    
    String decodedResponse = new String(xmlMessageBytes, 0, resultLength,
            "UTF-8");
    
    return decodedResponse;
    
  2. Analyser le XML résultant. Ici vous pouvez obtenir les informations dont vous avez besoin et, par exemple, créer un POJO avec elle (ceci est un exemple de code pour l'analyse de LogoutRequest mais serait analogue pour les réponses):

    // Parse the XML. SAX approach, we just need the ID attribute
    SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
    
    // If we want to validate the doc we need to load the DTD
    // saxParserFactory.setValidating(true);
    
    // Get a SAXParser instance
    SAXParser saxParser = saxParserFactory.newSAXParser();
    
    // Parse it
    XMLhandler xmLhandler = new XMLhandler();
    saxParser.parse(new ByteArrayInputStream(xmlLogoutRequest.getBytes()),
            xmLhandler);
    
    // Return the SamlVO
    return xmLhandler.getSamlVO();
    

Pour mon cas d'utilisation, je ne suis intéressé que par quelques éléments, donc j'utilise SAXO:

public class XMLhandler extends DefaultHandler {

    private SamlVO samlVO;

    public XMLhandler() {
        samlVO = new SamlVO();
    }

    @Override
    public void startElement(String uri, String localName, String qName,
        Attributes attributes) throws SAXException {

        // Managing a LogoutRequest means that we are going to build a LogoutResponse
        if (qName.equals("samlp:LogoutRequest")) {
            // The ID value of a request will be the LogoutResponse's InReponseTo attribute 
            samlVO.setInResponseTo(attributes.getValue("ID"));
            // From the destination we can get the Issuer element
            String destination = attributes.getValue("Destination");
            if (destination != null) {
                URL destinationUrl = null;
                try {
                    destinationUrl = new URL(destination);
                } catch (MalformedURLException e) {
                     // TODO: We could set the server hostname (take it from a property), but this URL SHOULD be well formed!
                     e.printStackTrace();
                }
                samlVO.setIssuer(destinationUrl.getHost());
            }
        }   
    }

    public SamlVO getSamlVO() {
        return samlVO;
    }

}

J'espère que cela aide,

Luis

PS: vous pouvez aussi utiliser une bibliothèque comme OpenSAML

DefaultBootstrap.bootstrap();

HTTPRedirectDeflateDecoder decode = new HTTPRedirectDeflateDecoder(new BasicParserPool());
BasicSAMLMessageContext<LogoutRequest, ?, ?> messageContext = new BasicSAMLMessageContext<LogoutRequest, SAMLObject, SAMLObject>();
messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(request));
decode.decode(messageContext);
XMLObjectBuilderFactory builderFactory = org.opensaml.Configuration.getBuilderFactory();
LogoutRequestBuilder logoutRequestBuilder = (LogoutRequestBuilder) builderFactory.getBuilder(LogoutRequest.DEFAULT_ELEMENT_NAME);
LogoutRequest logoutRequest = logoutRequestBuilder.buildObject();
logoutRequest = (LogoutRequest) messageContext.getInboundMessage();

Mais préparez-vous à inclure quelques bibliothèques dans votre CLASSPATH !!!


13
2018-01-31 14:08



Demander du code est un peu exagéré, mais le traitement de base est que le SP valide la réponse SAMLResponse, notamment pour la bonne formation, la présence des valeurs requises, le protocole correct et toute autre validation spécifique au SP (contraintes de temps, correspondance de données, etc. ), mappe l'utilisateur identifié dans le jeton à l'utilisateur sur SP (peut impliquer la création d'un utilisateur) et transfère l'utilisateur à la ressource demandée.


1
2017-07-13 18:50



Voici comment je le fais en Java. J'utilise XMLBeans pour analyser le SAMLResponse, puis le déchiffre (s'il est chiffré), puis vérifie la signature:

WebBrowserSSOAuthConsumerService


1
2017-07-14 15:23