[keycloak-user] JBoss EAP 7.0 - keycloak-wildfly-adapter-dist-4.3.0.Final - KeycloakConfigResolver called on unprotected Resources

Dmitry Telegin dt at acutus.pro
Tue Oct 30 01:29:56 EDT 2018


Hello Andreas,

I'm afraid this is by design - one of the reasons may be Java EE programmatic security [1], where the application can instigate login even from the resources not protected by web.xml security constraints.

But I don't think you should be bothered - in your resolver, there is a cache for KeycloakDeployments, and cache calls are cheap (and you will always have a cache hit, except for the very first invocation).

Even if there had been the code to determine whether the resolver should or should not kick in, according to web.xml rules, - this code would have been more expensive, let alone it would have broken programmatic security. If you are super determined, you can craft a simple performance test using e.g. Gatling [2] - I'm pretty sure the results for resolver vs. no resolver will differ insignificantly.

[1] https://docs.oracle.com/javaee/7/tutorial/security-webtier003.htm
[2] https://gatling.io/

Cheers,
Dmitry Telegin
CTO, Acutus s.r.o.
Keycloak Consulting and Training

Pod lipami street 339/52, 130 00 Prague 3, Czech Republic
+42 (022) 888-30-71
E-mail: info at acutus.pro

On Sat, 2018-10-27 at 07:21 +0000, Andreas Lau wrote:
> Hey guys, sorry for bouncing that topic again, but this issue currently is a show stopper for us. We need to have multi-tenancy for our application, but as it works now it is not feasible.
> So we desparatly ask for your help.
> 
> Am 24. Oktober 2018 17:16:23 MESZ schrieb Andreas Lau <andreas.lau at outlook.com>:
> 
> Hello,
> we deployed a jsf primfaces application on a JBoss EAP 7.0 System. We have to support multiple clients using multi tenancy. We followed the instructions of the documentation [1] to build up a CustomKeycloakConfigResolver.
> We configured the web.xml like this:
> [web.xml]
> <web-app>
> ...
> <security-constraint>
>  <web-resource-collection>
>   <web-resource-name>portal</web-resource-name>
>   <url-pattern>/portal/*</url-pattern>
>  </web-resource-collection>
>  <auth-constraint>
>   <role-name>user</role-name>
>  </auth-constraint>
> </security-constraint>
> <security-constraint>
>  <web-resource-collection>
>   <web-resource-name>public</web-resource-name>
>   <url-pattern>/portal/pages/willkommen.jsf</url-pattern>
>   <url-pattern>/portal/pages/logout.jsf</url-pattern>
>  </web-resource-collection>
> </security-constraint>
> 
> <login-config>
>  <auth-method>KEYCLOAK</auth-method>
> </login-config>
> 
> <security-role>
>  <role-name>user</role-name>
> </security-role>
> ...
> <context-param>
>  <param-name>keycloak.config.resolver</param-name>
>  <param-value>de.sample.security.MandantBasedKeycloakConfigResolver</param-value>
> </context-param>
> ...
> </web-app>
> 
> As you can see everything under portal is restricted with two exceptions. The code of MandantBasedKeycloakConfigResolver is straight forward and adapted to the example code [2]. In our example we consider that the url has a query parameter that provides an id which we can map to a corresponding keycloak.json file. A sample would be "https://localhost:8443/SampleApp/portal/pages/willkommen.jsf?kId=1".
> 
> After deployment I realized, that the KeycloakConfigResolver is called 44 times (see log entries [3]). As it turns out the KeycloakConfigResolver.resolve() methode is called for every resource that is loaded through get requests to display the site. I did not expect that many invocation, since the resources are not protected.
> 
> Can you please tell me if this behaviour is correct? What is my error in adopting the mulity tenancy sample? How can we prevent/workaround that many calls?
> While researching I found a jira https://issues.jboss.org/browse/KEYCLOAK-8616 with a potentially similar problem. Here they use keycloak to secure a spring boot application and have troubles when a sso redirection occurs.
> 
> Regards,
> Andreas
> 
> [1] https://www.keycloak.org/docs/latest/securing_apps/index.html#_multi_tenancy
> 
> [2] public KeycloakDeployment resolve(HttpFacade.Request request) {
> 
>         LOGGER.debug("MandantBasedKeycloakConfigResolver.resolve() - counter:" + counter++);
>         final String mandantId = request.getFirstParam("kId");
>         LOGGER.debug("MandantBasedKeycloakConfigResolver.resolve() - requestFirstParam(kId):" + mandantId);
>         LOGGER.debug("MandantBasedKeycloakConfigResolver.resolve() - uri:" + request.getURI());
> 
>         if (mandantId == null || mandantId.isEmpty()) {
>             // throw new IllegalStateException("Not able to resolve realm for parameter kId - Parameter not found!");
>             return null;
>         }
> 
>         KeycloakDeployment deployment = cache.get(mandantId);
>         if (deployment == null) {
> 
>             String keycloakConfigFilename = resolveKeycloakConfigFilename(mandantId);
> 
>             InputStream is = getClass().getResourceAsStream("/" + keycloakConfigFilename);
>             if (is == null) {
>                 // throw new IllegalStateException("Not able to find the file /" + keycloakConfigFilename);
>                 return null;
>             }
>             LOGGER.debug("MandantBasedKeycloakConfigResolver.resolve() - is IS==null?:" + (is == null));
> 
>             deployment = KeycloakDeploymentBuilder.build(is);
>             cache.put(mandantId, deployment);
>         }
> 
>         return deployment;
>     }
> 
> [3]
> 17:28:43,281 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-4) MandantBasedKeycloakConfigResolver.resolve() - counter:0
> 17:28:50,215 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-4) MandantBasedKeycloakConfigResolver.resolve() - requestFirstParam(kId):3
> 17:28:50,228 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-4) MandantBasedKeycloakConfigResolver.resolve() - uri:https://localhost:8443/SampleApp/portal/pages/willkommen.jsf?kId=3
> 17:28:50,229 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-4) MandantBasedKeycloakConfigResolver.resolve() - is IS==null?:false
> 17:28:50,496 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-4) MandantBasedKeycloakConfigResolver.resolve() - counter:1
> 17:28:50,496 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-4) MandantBasedKeycloakConfigResolver.resolve() - requestFirstParam(kId):3
> 17:28:50,496 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-4) MandantBasedKeycloakConfigResolver.resolve() - uri:https://localhost:8443/SampleApp/portal/pages/willkommen.jsf?kId=3
> 17:28:50,496 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-4) MandantBasedKeycloakConfigResolver.resolve() - counter:2
> 17:28:50,496 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-4) MandantBasedKeycloakConfigResolver.resolve() - requestFirstParam(kId):3
> 17:28:50,496 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-4) MandantBasedKeycloakConfigResolver.resolve() - uri:https://localhost:8443/SampleApp/portal/pages/willkommen.jsf?kId=3
> 17:28:50,933 INFO  [stdout] (default task-4) INIT Willkommen
> 17:28:50,933 INFO  [stdout] (default task-4) initialized mandant <<<<<<<<<<<<<
> 
> 17:28:51,168 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-5) MandantBasedKeycloakConfigResolver.resolve() - counter:3
> 17:28:51,168 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-5) MandantBasedKeycloakConfigResolver.resolve() - requestFirstParam(kId):null
> 17:28:51,168 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-5) MandantBasedKeycloakConfigResolver.resolve() - uri:https://localhost:8443/SampleApp/javax.faces.resource/components.css.jsf;jsessionid=6YidBEhtdxxI3NAASHOPab5bdBN_JAOjgqf8qHeh.localhost?ln=primefaces&v=6.1
> 17:28:51,168 ERROR [io.undertow.request] (default task-5) UT005023: Exception handling request to /SampleApp/javax.faces.resource/components.css.jsf;jsessionid=6YidBEhtdxxI3NAASHOPab5bdBN_JAOjgqf8qHeh.localhost: java.lang.IllegalStateException: Not able to resolve realm for parameter kId - Parameter not found!
> at de.sample.security.MandantBasedKeycloakConfigResolver.resolve(MandantBasedKeycloakConfigResolver.java:46) [classes:]
> at org.keycloak.adapters.AdapterDeploymentContext.resolveDeployment(AdapterDeploymentContext.java:88) [keycloak-adapter-core-4.0.0.Final.jar:4.0.0.Final]
> at org.keycloak.adapters.PreAuthActionsHandler.preflightCors(PreAuthActionsHandler.java:107) [keycloak-adapter-core-4.0.0.Final.jar:4.0.0.Final]
> at org.keycloak.adapters.PreAuthActionsHandler.handleRequest(PreAuthActionsHandler.java:79) [keycloak-adapter-core-4.0.0.Final.jar:4.0.0.Final]
> at org.keycloak.adapters.undertow.ServletPreAuthActionsHandler.handleRequest(ServletPreAuthActionsHandler.java:68) [keycloak-undertow-adapter-4.0.0.Final.jar:4.0.0.Final]
> at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:285) [undertow-servlet-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:264) [undertow-servlet-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81) [undertow-servlet-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:175) [undertow-servlet-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.server.Connectors.executeRootHandler(Connectors.java:324) [undertow-core-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:803) [undertow-core-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_112]
> at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_112]
> at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_112]
> 
> .......
> 
> 17:28:51,824 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-50) MandantBasedKeycloakConfigResolver.resolve() - counter:43
> 17:28:51,825 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-50) MandantBasedKeycloakConfigResolver.resolve() - requestFirstParam(kId):null
> 17:28:51,825 DEBUG [de.sample.security.MandantBasedKeycloakConfigResolver] (default task-50) MandantBasedKeycloakConfigResolver.resolve() - uri:https://localhost:8443/SampleApp/javax.faces.resource/customJs/customJavaScript.js.jsf;jsessionid=6YidBEhtdxxI3NAASHOPab5bdBN_JAOjgqf8qHeh.localhost?ln=ultima-layout
> 17:28:51,825 ERROR [io.undertow.request] (default task-50) UT005023: Exception handling request to /SampleApp/javax.faces.resource/customJs/customJavaScript.js.jsf;jsessionid=6YidBEhtdxxI3NAASHOPab5bdBN_JAOjgqf8qHeh.localhost: java.lang.IllegalStateException: Not able to resolve realm for parameter kId - Parameter not found!
> at de.sample.security.MandantBasedKeycloakConfigResolver.resolve(MandantBasedKeycloakConfigResolver.java:46) [classes:]
> at org.keycloak.adapters.AdapterDeploymentContext.resolveDeployment(AdapterDeploymentContext.java:88) [keycloak-adapter-core-4.0.0.Final.jar:4.0.0.Final]
> at org.keycloak.adapters.PreAuthActionsHandler.preflightCors(PreAuthActionsHandler.java:107) [keycloak-adapter-core-4.0.0.Final.jar:4.0.0.Final]
> at org.keycloak.adapters.PreAuthActionsHandler.handleRequest(PreAuthActionsHandler.java:79) [keycloak-adapter-core-4.0.0.Final.jar:4.0.0.Final]
> at org.keycloak.adapters.undertow.ServletPreAuthActionsHandler.handleRequest(ServletPreAuthActionsHandler.java:68) [keycloak-undertow-adapter-4.0.0.Final.jar:4.0.0.Final]
> at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) [undertow-core-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:285) [undertow-servlet-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:264) [undertow-servlet-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81) [undertow-servlet-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:175) [undertow-servlet-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.server.Connectors.executeRootHandler(Connectors.java:324) [undertow-core-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:803) [undertow-core-1.3.31.Final-redhat-3.jar:1.3.31.Final-redhat-3]
> at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_112]
> at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_112]
> at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_112]
> ________________________________
> keycloak-user mailing list
> keycloak-user at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/keycloak-user
> _______________________________________________
> keycloak-user mailing list
> keycloak-user at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/keycloak-user


More information about the keycloak-user mailing list