# Issue with SAML Response Parsing: XML Parsing Error in Keycloak 22.0.4 - The entity name must immediately follow the '&' in the entity reference

**URL:** <https://forum.keycloak.org/t/issue-with-saml-response-parsing-xml-parsing-error-in-keycloak-22-0-4-the-entity-name-must-immediately-follow-the-in-the-entity-reference/23826>\
**Category:** Configuring the server\
**Tags:** saml\
**Created:** [December 21, 2023, 10:53am UTC](https://forum.keycloak.org/t/issue-with-saml-response-parsing-xml-parsing-error-in-keycloak-22-0-4-the-entity-name-must-immediately-follow-the-in-the-entity-reference/23826 "2023-12-21T10:53:02Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![lwzl](https://avatars.discourse-cdn.com/v4/letter/l/e36b37/32.png) [@lwzl](https://forum.keycloak.org/u/lwzl)\
**Post date:** [December 21, 2023, 10:53am UTC](https://forum.keycloak.org/t/issue-with-saml-response-parsing-xml-parsing-error-in-keycloak-22-0-4-the-entity-name-must-immediately-follow-the-in-the-entity-reference/23826/1 "2023-12-21T10:53:02Z")

</div>

Hi,

I’m experiencing a challenging issue with SAML response parsing in Keycloak version 22.0.4 and would greatly appreciate any insights or suggestions.

**Issue Description:** When receiving a SAML response from the German portal “Elster” / “Mein Unternehmenskonto” (acting as the identity provider), Keycloak logs a fatal XML parsing error, which i received from the logs:

```auto
[Fatal Error] :1:24: The entity name must immediately follow the '&' in the entity reference.
2023-12-21 09:53:34,838 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-5) Uncaught server error: org.keycloak.broker.provider.IdentityBrokerException: Could not process response from SAML identity provider.

```

> **More verbose error message**
>
> [Fatal Error] :1:24: The entity name must immediately follow the ‘&’ in the entity reference.
> 
> 2023-12-21 10:48:24,621 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-22) Uncaught server error: org.keycloak.broker.provider.IdentityBrokerException: Could not process response from SAML identity provider  
> at org.keycloak.broker.saml.SAMLEndpoint$Binding.handleLoginResponse(SAMLEndpoint.java:596)  
> at org.keycloak.broker.saml.SAMLEndpoint$Binding.handleSamlResponse(SAMLEndpoint.java:679)  
> at org.keycloak.broker.saml.SAMLEndpoint$Binding.execute(SAMLEndpoint.java:278)  
> at org.keycloak.broker.saml.SAMLEndpoint.postBinding(SAMLEndpoint.java:189)  
> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)  
> at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)  
> at java.base/java.lang.reflect.Method.invoke(Method.java:568)  
> at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:154)  
> at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:118)  
> at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:560)  
> at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:452)  
> at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:413)  
> at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:321)  
> at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:415)  
> at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:378)  
> at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:174)  
> at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:142)  
> at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:168)  
> at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:131)  
> at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:33)  
> at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:429)  
> at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:240)  
> at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:154)  
> at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:321)  
> at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:157)  
> at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:229)  
> at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:82)  
> at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:147)  
> at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:84)  
> at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:44)  
> at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)  
> at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)  
> at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)  
> at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:58)  
> at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:36)  
> at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)  
> at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)  
> at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)  
> at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$0(QuarkusRequestFilter.java:82)  
> at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)  
> at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)  
> at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)  
> at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)  
> at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)  
> at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)  
> at java.base/java.lang.Thread.run(Thread.java:833)
> 
> Caused by: java.lang.RuntimeException: Could not parse xml element  
> at org.keycloak.broker.saml.mappers.XPathAttributeMapper.lambda$applyXPath$4(XPathAttributeMapper.java:219)  
> at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)  
> at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)  
> at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)  
> at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)  
> at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)  
> at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)  
> at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)  
> at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)  
> at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)  
> at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)  
> at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)  
> at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)  
> at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)  
> at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)  
> at java.base/java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1707)  
> at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)  
> at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)  
> at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)  
> at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)  
> at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)  
> at org.keycloak.broker.saml.mappers.XPathAttributeMapper.findAttributeValuesInContext(XPathAttributeMapper.java:241)  
> at org.keycloak.broker.saml.mappers.XPathAttributeMapper.preprocessFederatedIdentity(XPathAttributeMapper.java:147)  
> at org.keycloak.services.resources.IdentityBrokerService.lambda$authenticated$0(IdentityBrokerService.java:524)  
> at java.base/java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1707)  
> at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)  
> at org.keycloak.services.resources.IdentityBrokerService.authenticated(IdentityBrokerService.java:521)  
> at org.keycloak.broker.saml.SAMLEndpoint$Binding.handleLoginResponse(SAMLEndpoint.java:592)
> 
> … 46 more
> 
> Caused by: ParsingException [location=null]org.keycloak.saml.common.exceptions.ParsingException: PL00074: Parsing Error:The entity name must immediately follow the ‘&’ in the entity reference  
> at org.keycloak.saml.common.DefaultPicketLinkLogger.parserError(DefaultPicketLinkLogger.java:486)  
> at org.keycloak.saml.common.util.DocumentUtil.getDocument(DocumentUtil.java:142)  
> at org.keycloak.broker.saml.mappers.XPathAttributeMapper.lambda$applyXPath$4(XPathAttributeMapper.java:213)
> 
> … 73 more
> 
> Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 24; The entity name must immediately follow the ‘&’ in the entity reference  
> at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:262)  
> at java.xml/com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:342)  
> at org.keycloak.saml.common.util.DocumentUtil.getDocument(DocumentUtil.java:138)
> 
> … 74 more

**Context:**

- The data sent from the identity provider includes various fields, some with special characters like ‘ö’, ‘ü’, ‘ß’ and ‘&’. For instance, the street name contains ‘ö’ and ‘ß’, and the company name includes ‘&’.
- I have already ensured that the JVM is using UTF-8 encoding (`JAVA_OPTS` set to `-Dfile.encoding=UTF-8`).
- Keycloak version: 22.0.4.
- Keycloak is deployed in a kubernetes cluster using a helm configuration.

**Information that should be sent from the IdP**

This data should be sent from the german portal “Elster” / “Mein Unternehmenskonto”, which is the identity provider which sends the response. I replaced some regular, non special characters with abc or 123.

**Firmenname** : abcde - abcd & Abcdefgh\_12345  
**Registernummer** : 12345678901  
**Registerart** : HRB  
**Registergericht** : Amtsgericht Bersenbrück  
**Rechtsform** : Ges. mit beschr. Haftung und Co.KG  
**Anschrift** : Schönmannstraße 123, 12345 Town, Deutschland  
**Steuernummer (wird nicht weitergegeben)**: 1234567890123  
**Herkunft der Daten** : Finanzamt

In English:  
**Company name** : abcde - abcd & Abcdefgh\_12345  
**Register number** : 12345678901  
**Register type** : HRB  
**Register court** : Amtsgericht Bersenbrück  
**Legal form** : Ges. mit beschr. Haftung und Co.KG  
**Legal address** : Schönmannstraße 123, 12345 Town, Deutschland  
**Tax number (will not be passed on)**: 1234567890123  
**Origin of the data** : Finanzamt

**SAML Response Details:**

- I used SAML-tracer for Chrome to capture the SAML response.
- The response includes standard SAML and XML signatures, status, and an encrypted assertion.

this is my saml response that i recorded with saml-tracer for chrome.

```xml
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                 Destination="mydest/muk-saml/endpoint"
                 ID="myid"
                 InResponseTo="ID_myid"
                 IssueInstant="2023-12-21T09:48:24.022Z"
                 Version="2.0"
                 >
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://e4k-portal.een.elster.de</saml2:Issuer>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            <ds:SignatureMethod Algorithm="http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1" />
            <ds:Reference URI="#_myReferenceUri">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                <ds:DigestValue>myDigestValue</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>mysigval</ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>mycert</ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>
    <saml2p:Status>
        <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
    </saml2p:Status>
    <saml2:EncryptedAssertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
        <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
                            Id="myId"
                            Type="http://www.w3.org/2001/04/xmlenc#Element"
                            >
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#aes256-gcm" />
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <xenc:EncryptedKey Id="myId">
                    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#rsa-oaep">
                        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                        <xenc11:MGF xmlns:xenc11="http://www.w3.org/2009/xmlenc11#"
                                    Algorithm="http://www.w3.org/2009/xmlenc11#mgf1sha256"
                                    />
                    </xenc:EncryptionMethod>
                    <xenc:CipherData>
                        <xenc:CipherValue>myciphervalue</xenc:CipherValue>
                    </xenc:CipherData>
                </xenc:EncryptedKey>
            </ds:KeyInfo>
            <xenc:CipherData>
                <xenc:CipherValue>

```

**Questions:**

Are there recommended configurations or approaches to handle special characters in SAML responses, especially when dealing with non-English characters and symbols like ‘&’?

Has anyone experienced similar XML parsing issues with special characters in SAML responses in Keycloak?

Any advice on further diagnosing or logging this specific issue to isolate the problematic part of the SAML response?

Thank you in advance for any help.  
Let me know if there’s any more information i can provide.

Best regards,  
Lukas
