opensaml encoding problems with xml to base64

Jason Novotny jason.novotny at gmail.com
Tue Nov 4 23:16:37 EST 2014


Hi,

I'm having problems integrating SSO inbound and outbound with my 
Identity Provider in that the AuthnRequest I get back will have some 
strange bytes that I've had to write a hack to deal with and the 
SAMLResponse that I send out apparently is not decoded into proper XML. 
Googling around I see a number of ways to marshall/unmarshall and I'd 
like to know which way is the approved way.

Here's the code I was using for converting a base64 AuthnRequest into a 
org.w3c.dom.Document:


     private Document parseDocument(String encoded) throws 
VeoSSOServiceException {
         try {
             return parseDocument1(encoded);
         } catch (Exception e) {
             try {
                 return parseDocument2(encoded);
             } catch (Exception ef) {
                 // god help us
             }
         }
         throw new VeoSSOServiceException("Can't parse the encoded data!");
     }

     private Document parseDocument1(String encoded) throws Exception {
         byte[] base64DecodedResponse = Base64.decode(encoded);
         ByteArrayInputStream is = new 
ByteArrayInputStream(base64DecodedResponse);
         DocumentBuilderFactory documentBuilderFactory = 
DocumentBuilderFactory.newInstance();
         documentBuilderFactory.setNamespaceAware(true);
         DocumentBuilder docBuilder = 
documentBuilderFactory.newDocumentBuilder();
         StringWriter writer = new StringWriter();
         IOUtils.copy(is, writer, "UTF-8");
         encoded = writer.toString().replaceAll("[^\\p{ASCII}]", "");
         //encoded = 
writer.toString().substring(writer.toString().indexOf("<"));
         is = new ByteArrayInputStream(encoded.getBytes());
         Document document = docBuilder.parse(is);
         return document;
     }


     private Document parseDocument2(String encoded) throws Exception {
         byte[] samlBytes = Base64.decode(encoded);
         Inflater inflater = new Inflater(true);
         inflater.setInput(samlBytes);
         ByteArrayOutputStream stream = new ByteArrayOutputStream();
         byte[] buffer = new byte[1024];
         while (!inflater.finished()) {
             int count = inflater.inflate(buffer);
             if (count == 0)
                 break;
             stream.write(buffer, 0, count);
         }
         stream.close();
         samlBytes = stream.toByteArray();
         DocumentBuilderFactory documentBuilderFactory = 
DocumentBuilderFactory.newInstance();
         documentBuilderFactory.setNamespaceAware(true);
         DocumentBuilder docBuilder = 
documentBuilderFactory.newDocumentBuilder();

         ByteArrayInputStream is = new ByteArrayInputStream(samlBytes);
         Document document = docBuilder.parse(is);
         return document;
     }

I'm also wondering how I should be encoding my SAMLresponse. Here is the 
code I'm currently using:

public VeoSSOResult parseSAMLRequest(String samlRequestStr) throws 
VeoSSOServiceException {
         try {
             VeoSSOResult veoSSOResult = new VeoSSOResult();

             Document document = parseDocument(samlRequestStr);

             Element metadataRoot = document.getDocumentElement();

             QName qName = new QName(metadataRoot.getNamespaceURI(), 
metadataRoot.getLocalName(), "saml2p");

             // get an unmarshaller
             Unmarshaller unmarshaller = 
Configuration.getUnmarshallerFactory().getUnmarshaller(qName);

             Object object = unmarshaller.unmarshall(metadataRoot);
             AuthnRequest authnRequest = (AuthnRequest) object;
             String response = createSAMLResponse(authnRequest);
             veoSSOResult.setBase64(response);
veoSSOResult.setDestinationURL(authnRequest.getAssertionConsumerServiceURL());
             return veoSSOResult;
         } catch (Exception e) {
             throw new VeoSSOServiceException("No good", e);
         }
     }

     private void authenticateRequest(AuthnRequest authnRequest) {

         // TODO anything we care about validating from AuthnRequest input?

     }

     public String createSAMLResponse(AuthnRequest authnRequest) throws 
VeoSSOServiceException, IOException {

         authenticateRequest(authnRequest);
         VeoSSOResponseInfo info = null;
         try {
             info = new VeoSSOResponseInfo();
         } catch (Exception e) {
             throw new VeoSSOServiceException("Unable to initiate:", e);
         }
         final SAMLObjectBuilder<Response> responseBuilder =
             (SAMLObjectBuilder<Response>) 
builderFactory.getBuilder(Response.DEFAULT_ELEMENT_NAME);
         final Response responseMessage = responseBuilder.buildObject();

         responseMessage.setID(createID());
         responseMessage.setVersion(SAMLVersion.VERSION_20);
         responseMessage.setIssueInstant(new DateTime());
         responseMessage.setInResponseTo(authnRequest.getID());
responseMessage.setDestination(authnRequest.getAssertionConsumerServiceURL());

         final Issuer issuer = buildIssuer(info);
         responseMessage.setIssuer(issuer);

         final Status status = buildStatus(info);
         responseMessage.setStatus(status);

         final Assertion assertion = buildAssertion(info);
         responseMessage.getAssertions().add(assertion);

         ResponseMarshaller marshaller = new ResponseMarshaller();

         Element plain = null;
         String encodedRequestMessage;
         try {
             plain = marshaller.marshall(responseMessage);
             String samlResponse = XMLHelper.nodeToString(plain);
             byte[] xmlBytes = samlResponse.getBytes("UTF-8");
             String base64Encoded = Base64.encodeBytes(xmlBytes);

             encodedRequestMessage =
                 Base64.encodeBytes(samlResponse.getBytes(),
                     Base64.DONT_BREAK_LINES);

             return base64Encoded;
         } catch (MarshallingException e) {
             throw new VeoSSOServiceException("Unable to marshall 
SAMLResponse:", e);
         }
  }

Any help is greatly appreciated!

Thanks, Jason


More information about the dev mailing list