Over the past few months I have had a few ServiceNow customers contact me with errors that they were seeing when using SiteMinder as their SAML federation service.
THE ISSUE
When their users would perform an Identity Provider (IdP) initiated login, their ServiceNow instance would throw the following error in the system log:
java.lang.IllegalArgumentException: prefix cannot be “null” when creating a QName
Caused by error in Script Include: ‘SAML2’ at line 4138: document.normalizeDocument();
39: var metadataRoot = document.getDocumentElement();
40:
==> 41: var qName = new QName(metadataRoot.getNamespaceURI(), metadataRoot.getLocalName(), metadataRoot.getPrefix());
42:
The customers observed that SiteMinder creates a SAML2 Response without any namespace prefix:
1 | <Response xmlns="urn:oasis:names:tc:SAML:2.0:protocol" … |
When we are typically looking for something like this:
1 | <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" |
According to the JavaDoc on a Node object, if there is no prefix in an XML document, it will return null. However, this will conflict with the QName constructor. According to the QName JavaDoc, if there is no prefix, we need to use a different constructor that omits the prefix altogether.
PROPOSED SOLUTION
New Update: If you download the update set that provides Additional SAML 2.0 Configuration Options then you will not need to modify the SAML scripts as outlined below.
Change SAML2 script include (line 41) from:
1 | var qName = new QName(metadataRoot.getNamespaceURI(), metadataRoot.getLocalName(), metadataRoot.getPrefix()); |
to be:
1 2 3 4 5 6 | var qName = ""; if( metadataRoot.getPrefix() ){ qName = new QName(metadataRoot.getNamespaceURI(), metadataRoot.getLocalName(), metadataRoot.getPrefix()); } else { qName = new QName(metadataRoot.getNamespaceURI(), metadataRoot.getLocalName()); } |
This will first detect if there is a prefix on the SAML Response. If there is not, then it will call the appropriate QName constructor.