Details

      Description

      In the old picketlink SAML configuration the ASSERTION_SESSION_ATTRIBUTE_NAME option stores into the session the DOM document of the assertion, this way the assertion can be replayed as a STS token. Right now the problem with the RH-SSO adapter is that the only thing that can be recovered is the AssertionType from the SamlPrincipal (see the javadoc), and this is a java object that have been created from the XML, so, if it's converted again to XML, the signature can be not OK (because different prefixes for example).

      I have exemplified the problem with this code (which more or less uses keycloak classes):

              byte[] bytes = Base64.getDecoder().decode(Files.readAllBytes(new File("saml-idp.base64").toPath()));
              SAMLDocumentHolder holder = SAMLRequestParser.parseResponseDocument(bytes);
              // dom assertion
              Element assertion = DocumentUtil.getElement(holder.getSamlDocument(), new QName(JBossSAMLConstants.ASSERTION.get()));
              Document doc = DocumentUtil.createDocument();
              doc.adoptNode(assertion);
              doc.appendChild(assertion);
              System.err.println("Assertion DOM : " + DocumentUtil.asString(doc));
              // java object assertion
              ResponseType responseType = (ResponseType) holder.getSamlObject();
              AssertionType assertionType = AssertionUtil.getAssertion(holder, responseType, null);
              System.err.println("Assertion Java: " + AssertionUtil.asString(assertionType));
              // get certificate and validate signature
              String certBase64 = DocumentUtil.getElement(holder.getSamlDocument(),
                          new QName("http://www.w3.org/2000/09/xmldsig#", "X509Certificate"))
                      .getTextContent();
              CertificateFactory cf = CertificateFactory.getInstance("X.509");
              Certificate cert = cf.generateCertificate(new ByteArrayInputStream(Base64.getMimeDecoder().decode(certBase64)));
              PublicKey pubkey = cert.getPublicKey();
              System.err.println("Signature DOM : " + AssertionUtil.isSignatureValid(doc.getDocumentElement(), pubkey));
              System.err.println("Signature Java: " + AssertionUtil.isSignatureValid(AssertionUtil.asDocument(assertionType).getDocumentElement(), pubkey));
      

      The original assertion in the saml-idp.base64 file is <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"... while the transformed one is <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"....

      Therefore the signature using DOM is OK but the signature with java is KO. If keycloak wants to allow this, needs to add the Assertion as a DOM document too (unmodified). This way the assertion is exactly as it was received (not parsed and transformed into an object). I have checked and the original SAML response DOM or String is not stored anywhere. So the idea would be just adding the DOM representation in the principal too, to let the apps recover the Assertion unmodified.

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  rhn-support-rmartinc Ricardo Martin Camarero
                  Reporter:
                  rhn-support-rmartinc Ricardo Martin Camarero
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  4 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: