We’re trying setup Keycloak (version 20.0.1) with an EHerkenning/EIDAS (Dutch/European identity system for businesses) Identity provider using SAML.
We can connect with the EHerkenning/EIDAS broker (their login page is shown). The response posted to the Keycloak endpoint however causes an exception. Keycloak displays “Invalid response from identity provider.”
In the Keycloak logs we found the following error;
2022-11-09 14:01:30,735 ERROR [org.keycloak.saml.common] (executor-thread-0) Error in base64 decoding saml message.: java.lang.RuntimeException: PL00062: Parser : Unknown tag:EncryptedAttribute::location=Line number = 159
Column number = 252
System Id = null
Public Id = null
Location Uri= null
CharacterOffset = 35248
at org.keycloak.saml.common.DefaultPicketLinkLogger.parserUnknownTag(DefaultPicketLinkLogger.java:359)
at org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAttributeStatementParser.processSubElement(SAMLAttributeStatementParser.java:56)
at org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAttributeStatementParser.processSubElement(SAMLAttributeStatementParser.java:31)
at org.keycloak.saml.common.parsers.AbstractStaxParser.parse(AbstractStaxParser.java:97)
at org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionParser.processSubElement(SAMLAssertionParser.java:96)
at org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionParser.processSubElement(SAMLAssertionParser.java:34)
at org.keycloak.saml.common.parsers.AbstractStaxParser.parse(AbstractStaxParser.java:97)
at org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLResponseParser.processSubElement(SAMLResponseParser.java:77)
at org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLResponseParser.processSubElement(SAMLResponseParser.java:38)
at org.keycloak.saml.common.parsers.AbstractStaxParser.parse(AbstractStaxParser.java:97)
at org.keycloak.saml.processing.core.parsers.saml.SAMLParser.parse(SAMLParser.java:123)
at org.keycloak.saml.common.parsers.AbstractParser.parse(AbstractParser.java:98)
at org.keycloak.saml.common.parsers.AbstractParser.parse(AbstractParser.java:102)
at org.keycloak.saml.processing.api.saml.v2.response.SAML2Response.getSAML2ObjectFromStream(SAML2Response.java:389)
at org.keycloak.saml.SAMLRequestParser.parseResponseDocument(SAMLRequestParser.java:104)
at org.keycloak.broker.saml.SAMLEndpoint$PostBinding.extractResponseDocument(SAMLEndpoint.java:726)
at org.keycloak.broker.saml.SAMLEndpoint$Binding.handleSamlResponse(SAMLEndpoint.java:624)
at org.keycloak.broker.saml.SAMLEndpoint$Binding.execute(SAMLEndpoint.java:276)
at org.keycloak.broker.saml.SAMLEndpoint.postBinding(SAMLEndpoint.java:187)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:152)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:183)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:141)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:32)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:82)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:42)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:84)
at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:71)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:430)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$6.handle(VertxHttpRecorder.java:408)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
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:564)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
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:829)
We’re running out of ideas what causes this issue. It’s also hard to debug, because of the lack of details in the logging of Keycloak, even with verbose logging enabled.
Does anyone have any clue what is going wrong with the base64 decoding of the SAML response?
- We’ve tried to decode the response using saml tool, however SAML tool is also unable to decode the message.
- We’ve tried removing the newlines from the entire SAML response (both in the encrypted, base64 hashed attributes and the response as a whole). Every change made results in Keycloak not accepting the new base64 encoded SAML response or crashes Keycloak without any logging at all.