I am using Spring SAML, from IDP response I am receiving issuer as an attribute ID, So I wanted to change the response after receiving in spring saml, so I have overridden method unmarshall which will parse the message and changed the xml elements for this purpose. While doing this if I directly use the Element after parsing to unmarshall it is working but if I do dom manipulation it is giving the below exception. I am not getting why it is throwing exception in first code but not in second code attached below. How to make it work without converting again to string and get dom object.
Exception in thread "main" java.lang.IllegalArgumentException: local part cannot be "null" when creating a QName
at java.xml/javax.xml.namespace.QName.<init>(QName.java:185)
at java.xml/javax.xml.namespace.QName.<init>(QName.java:129)
at org.opensaml.xml.util.XMLHelper.constructQName(XMLHelper.java:433)
at org.opensaml.xml.util.XMLHelper.getNodeQName(XMLHelper.java:171)
at org.opensaml.xml.io.UnmarshallerFactory.getUnmarshaller(UnmarshallerFactory.java:81)
at org.opensaml.xml.io.AbstractXMLObjectUnmarshaller.unmarshallChildElement(AbstractXMLObjectUnmarshaller.java:334)
at org.opensaml.xml.io.AbstractXMLObjectUnmarshaller.unmarshall(AbstractXMLObjectUnmarshaller.java:127)
at org.opensaml.xml.io.AbstractXMLObjectUnmarshaller.unmarshallChildElement(AbstractXMLObjectUnmarshaller.java:355)
at org.opensaml.xml.io.AbstractXMLObjectUnmarshaller.unmarshall(AbstractXMLObjectUnmarshaller.java:127)
at org.opensaml.ws.message.decoder.BaseMessageDecoder.unmarshallMessage(unmarshallMessage.java:208)
For the below code it is throwing exception as explained above.
protected XMLObject unmarshallMessage(InputStream messageStream) throws MessageDecodingException { log.debug("Parsing message stream into DOM document"); try { Document messageDoc = parserPool.parse(messageStream); Element messageElem = messageDoc.getDocumentElement(); Element elementsByTagName = (Element) messageElem.getElementsByTagName("saml2:Assertion").item(0); Element issuer = messageDoc.createElement("saml2:Issuer"); issuer.setTextContent("emIDAM"); issuer.setAttribute("Format", "urn:oasis:names:tc:SAML:2.0:nameid-format:entity"); log.debug("Unmarshalling message DOM"); Unmarshaller unmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(messageElem); if (unmarshaller == null) { log.debug("Unable to unmarshall message, no unmarshaller registered for message element " + XMLHelper.getNodeQName(messageElem)); throw new MessageDecodingException( "Unable to unmarshall message, no unmarshaller registered for message element " + XMLHelper.getNodeQName(messageElem)); } XMLObject message = unmarshaller.unmarshall(messageElem); return message; } catch (XMLParserException e) { log.error("Encountered error parsing message into its DOM representation", e); throw new MessageDecodingException("Encountered error parsing message into its DOM representation", e); } catch (UnmarshallingException e) { log.error("Encountered error unmarshalling message from its DOM representation", e); throw new MessageDecodingException("Encountered error unmarshalling message from its DOM representation", e); } catch (Exception e) { log.warn("Encountered error unmarshalling message from its DOM representation --->", e); throw new MessageDecodingException("Encountered error unmarshalling message from its DOM representation", e); } }
But for the below code it is working fine, because here I have again converted to string and created the input stream and then get the dom which is passed for unmarshalling.
protected XMLObject unmarshallMessage(InputStream messageStream) throws MessageDecodingException { log.debug("Parsing message stream into DOM document"); try { Document messageDoc = parserPool.parse(messageStream); Element messageElem = messageDoc.getDocumentElement(); Element elementsByTagName = (Element) messageElem.getElementsByTagName("saml2:Assertion").item(0); Element issuer = messageDoc.createElement("saml2:Issuer"); issuer.setTextContent("emIDAM"); issuer.setAttribute("Format", "urn:oasis:names:tc:SAML:2.0:nameid-format:entity"); //converting again to string and getting dom String xml = XMLHelper.nodeToString(messageElem); messageStream = new ByteArrayInputStream(xml.getBytes()); messageDoc = parserPool.parse(messageStream); messageElem = messageDoc.getDocumentElement(); log.debug("Unmarshalling message DOM"); Unmarshaller unmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(messageElem); if (unmarshaller == null) { log.debug("Unable to unmarshall message, no unmarshaller registered for message element " + XMLHelper.getNodeQName(messageElem)); throw new MessageDecodingException( "Unable to unmarshall message, no unmarshaller registered for message element " + XMLHelper.getNodeQName(messageElem)); } XMLObject message = unmarshaller.unmarshall(messageElem); return message; } catch (XMLParserException e) { log.error("Encountered error parsing message into its DOM representation", e); throw new MessageDecodingException("Encountered error parsing message into its DOM representation", e); } catch (UnmarshallingException e) { log.error("Encountered error unmarshalling message from its DOM representation", e); throw new MessageDecodingException("Encountered error unmarshalling message from its DOM representation", e); } catch (Exception e) { log.warn("Encountered error unmarshalling message from its DOM representation --->", e); throw new MessageDecodingException("Encountered error unmarshalling message from its DOM representation", e); } }