Skip to content

XML validation fails to load schemas in OSGi context #382

Description

@sandro-h

Hi, this is a rather specific problem, I suppose: we're using java-saml in a plugin for a third-party service. The plugin is loaded by an OSGi framework in this service. We don't have any control over the OSGi bundle manifests.

In this context, XML validation during Auth.processResponse fails to load the schema resource files with MalformedURLException: unknown protocol: bundle:

jvm 1    | 2022-04-19 10:12:27,990  WARN [qtp1903462050-26] p.c.a.g.s.p.c.a.g.s.s.JavaSamlLogPropagator:97 [plugin-ch.adnovum.gocd.saml2.plugin] - org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema document 'bundle://00a4a7ff-512c-49a7-b4f0-ebbd54ac8a10_7.0:5/schemas/saml-schema-protocol-2.0.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getSchemaDocument1(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getSchemaDocument(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(Unknown Source)
jvm 1    | 	at java.xml/javax.xml.validation.SchemaFactory.newSchema(Unknown Source)
jvm 1    | 	at java.xml/javax.xml.validation.SchemaFactory.newSchema(Unknown Source)
jvm 1    | 	at com.onelogin.saml2.util.SchemaFactory.loadFromUrl(SchemaFactory.java:106)
jvm 1    | 	at com.onelogin.saml2.util.Util.validateXML(Util.java:305)
jvm 1    | 	at com.onelogin.saml2.authn.SamlResponse.isValid(SamlResponse.java:220)
[...]
jvm 1    | Caused by: java.net.MalformedURLException: unknown protocol: bundle
jvm 1    | 	at java.base/java.net.URL.<init>(Unknown Source)
jvm 1    | 	at java.base/java.net.URL.<init>(Unknown Source)
jvm 1    | 	at java.base/java.net.URL.<init>(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaParsingConfig.parse(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaParsingConfig.parse(Unknown Source)
jvm 1    | 	at java.xml/com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOMParser.parse(Unknown Source)
jvm 1    | 	... 148 common frames omitted

In general, resource loading works fine in the plugin. I'm not sure why it's not working specifically for the javax.xml.validation.SchemaFactory:newSchema call. I also must admit I don't know enough about OSGi to pinpoint what could be happening here.

At the moment, I'm working around this by using a custom SamlMessageFactory that creates SamlResponses with custom xml validation, using an adapted SchemaFactory which loads the schemas via getResourceAsStream instead of URLs:

public abstract class SchemaFactory {

    // Resource path string instead of URL:
    public static final String SAML_SCHEMA_METADATA_2_0 = "/schemas/saml-schema-metadata-2.0.xsd";
    public static final String SAML_SCHEMA_PROTOCOL_2_0 = "/schemas/saml-schema-protocol-2.0.xsd";

    // Pass resource string instead of URL:
    public static Schema loadFromUrl(String schemaResourcePath) throws SAXException {
        [...]

        // Loads this via getResourceAsStream instead of directly from URL:
        InputStream inputStream = SchemaFactory.class.getResourceAsStream(schemaResourcePath);
        return factory.newSchema(new StreamSource(inputStream));
    }
}

I figured I'd report it, in case you've seen this before and know a better solution, or perhaps you're willing to accept that workaround, though it unfortunately breaks the API of SchemaFactory.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions