1

i am trying to connect my Spring Boot application with Keycloak. The keycloak login is a passwordless login (OTP code in an authenticator app). There is an external page, where everybody can access, when the user clicks in "customers" the user must log in into keycloak. Only users with ADMIN role, can access to customers page.

I am having this error in my spring boot application after a user with admin role is authenticated:

2023-06-17T19:59:10.737+02:00 ERROR 8213 --- [nio-8081-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Filter execution threw an exception] with root cause

java.lang.StackOverflowError: null
    at org.springframework.util.ReflectionUtils.isEqualsMethod(ReflectionUtils.java:516) ~[spring-core-6.0.8.jar:6.0.8]
    at org.springframework.aop.support.AopUtils.isEqualsMethod(AopUtils.java:151) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:175) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.8.jar:6.0.8]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216) ~[spring-aop-6.0.8.jar:6.0.8]
    at jdk.proxy2/jdk.proxy2.$Proxy125.authenticate(Unknown Source) ~[na:na]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201) ~[spring-security-core-6.0.3.jar:6.0.3]
    at jdk.internal.reflect.GeneratedMethodAccessor10.invoke(Unknown Source) ~[na:na]
    at 
........

2023-06-17T19:59:10.747+02:00 DEBUG 8213 --- [nio-8081-exec-4] o.s.security.web.FilterChainProxy        : Securing GET /error?state=XIg20i762t2joGdc86aeXARAwo4JwxKw-m1E1E1pvB4%3D&session_state=0ae9a0ee-6bbb-48e8-a1f4-cca029be6d4e&code=5957c24f-ea25-4197-9b35-9c85c6e594fa.0ae9a0ee-6bbb-48e8-a1f4-cca029be6d4e.318d1d70-732d-47a5-8f8b-dd8bc45c1306
2023-06-17T19:59:10.750+02:00 DEBUG 8213 --- [nio-8081-exec-4] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2023-06-17T19:59:10.751+02:00 DEBUG 8213 --- [nio-8081-exec-4] o.s.s.w.a.i.FilterSecurityInterceptor    : Authorized filter invocation [GET /error?state=XIg20i762t2joGdc86aeXARAwo4JwxKw-m1E1E1pvB4%3D&session_state=0ae9a0ee-6bbb-48e8-a1f4-cca029be6d4e&code=5957c24f-ea25-4197-9b35-9c85c6e594fa.0ae9a0ee-6bbb-48e8-a1f4-cca029be6d4e.318d1d70-732d-47a5-8f8b-dd8bc45c1306] with attributes [permitAll]
2023-06-17T19:59:10.751+02:00 DEBUG 8213 --- [nio-8081-exec-4] o.s.security.web.FilterChainProxy        : Secured GET /error?state=XIg20i762t2joGdc86aeXARAwo4JwxKw-m1E1E1pvB4%3D&session_state=0ae9a0ee-6bbb-48e8-a1f4-cca029be6d4e&code=5957c24f-ea25-4197-9b35-9c85c6e594fa.0ae9a0ee-6bbb-48e8-a1f4-cca029be6d4e.318d1d70-732d-47a5-8f8b-dd8bc45c1306

On the browser, this is what appears after the keycloak authentication

enter image description here

this is my SecurityConfig code:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final KeycloakLogoutHandler keycloakLogoutHandler;

    public SecurityConfig(KeycloakLogoutHandler keycloakLogoutHandler) {
        this.keycloakLogoutHandler = keycloakLogoutHandler;
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests((authorizeRequests) -> authorizeRequests
                .requestMatchers("/customers*")
                .hasRole("ADMIN")
                .anyRequest()
                .permitAll());
        http
                .oauth2Login(oauth2 -> oauth2
                        .defaultSuccessUrl("/customers")
                        .failureUrl("/external"))
                .logout(logout -> logout
                        .logoutUrl("/logout")
                        .logoutSuccessUrl("/external")
                        .addLogoutHandler(keycloakLogoutHandler));

        http.oauth2ResourceServer((oauth2) -> oauth2
                .jwt(Customizer.withDefaults())
        );
        System.out.println("linea 55");
        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
        return http.getSharedObject(AuthenticationManagerBuilder.class)
                .build();
    }



This is my KeycloakLogoutHandler code

@Component automáticamente en el contexto de la aplicación.
public class KeycloakLogoutHandler implements LogoutHandler {

    private static final Logger logger = LoggerFactory.getLogger(KeycloakLogoutHandler.class);
    private final RestTemplate restTemplate; //instancia de la clase RestTemplate, que es una clase de Spring que proporciona una forma conveniente de interactuar con servicios RESTful.

    public KeycloakLogoutHandler(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

  
    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response,
                       Authentication auth) {
        logoutFromKeycloak((OidcUser) auth.getPrincipal());
    }


    private void logoutFromKeycloak(OidcUser user) {
        String endSessionEndpoint = user.getIssuer() + "/protocol/openid-connect/logout";
        UriComponentsBuilder builder = UriComponentsBuilder
                .fromUriString(endSessionEndpoint)
                .queryParam("id_token_hint", user.getIdToken().getTokenValue());

        ResponseEntity<String> logoutResponse = restTemplate.getForEntity(
                builder.toUriString(), String.class);
        if (logoutResponse.getStatusCode().is2xxSuccessful()) {
            logger.info("Successfully logged out from Keycloak");
        } else {
            logger.error("Could not propagate logout to Keycloak");
        }
    }

}

This is my WebController code

@Controller
public class WebController {

    @Autowired
    private CustomerDAO customerDAO;

    @GetMapping(path = "/")
    public String index() {
        return "external";
    }

    @GetMapping("/logout")
    public String logout(HttpServletRequest request) throws Exception {
        request.logout();
        return "redirect:/";
    }

    @GetMapping(path = "/customers")
    public String customers(Principal principal, Model model) {


        return "customers";

    }
}

This is my application.properties file

# server port
server.port=8081

#client registration configuration:
spring.security.oauth2.client.registration.keycloak.client-id=appweb
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.scope=openid
keycloak.auth-server-url=http://localhost:8090/auth
keycloak.realm=demo
keycloak.resource=appweb

#OIDC provider configuration
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8090/realms/demo
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username

#configuration needed for validating JWT token against our keycloak server
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8090/realms/demo

logging.level.org.springframework.security=DEBUG
#si keycloak fuera https
keycloak.ssl-required=external

I expect the browser to be showing the customers page, not the "WhiteLabel Error"

Do you know how to fix the error?

Pau Perez
  • 11
  • 2

1 Answers1

1

There are quite a few causes of problems in your code:

  • you are missing a converter to turn Keycloak roles into Spring authorities. For OAuth2 clients, this is done for instance with a GrantedAuthoritiesMapper
  • you wrote hasRole("ADMIN") which requires the Authentication instance to contain an authority being exactly ROLE_ADMIN (not ADMIN or ROLE_admin for instance). So unless the user is granted with ROLE_ADMIN in Keycloak, or the authorities converter adds ROLE_ prefix, your expression won't match (you should probably consider hasAuthority("admin") or something instead).
  • Keycloak is fully compliant with OIDC (its OpenId configuration exposes an end_session_endpoint) => you should use OidcClientInitiatedLogoutSuccessHandler for logout
  • you have http.oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults()) in the middle of some OAuth2 client configuration, which makes me think that you expect your browser requests to be authorized with a Bearer access token. It won't: you are using oauth2Login => your requests are authorized with a session cookie, not a token.

Mixing OAuth2 client and resource server configurations in the same filter chain is a bad idea. Spring created separated starters for a reason:

  • requests to resource servers are authorized with a Bearer access token in the Authorization header. Resource servers are generally stateless (no session), and as so do not require CSRF protection. Also, the response status for unauthorized requests (access token missing or invalid) should be 401. Last, only token validity is a concern, not how it was acquired (which flow to use, with or without login) or revoked (logout).
  • requests to clients are authorized with sessions cookies and as so, require protection against CSRF attacks. Unauthorized requests to protected resources should be redirected to login (302 status). Last, clients are responsible for tokens acquisition, which requires login and logout when a user is involved.

Unless you intend to publicly expose some REST API endpoints, you should remove the resource server dependencies and configuration. If on the opposite, you have external OAuth2 clients consuming some REST endpoints in your app (clients that can authorize their requests with a Bearer access token), then define a second SecurityFilterChain bean to split client and resource server configurations.

When you have more than one SecurityFilterChain, all should be decorated with @Order(n) to define in which order they are tried and all but the last one should contain http.securityMatcher(...) to define to which resources it applies to. For instance, you'd have something like:

@Order(1)
SecurityFilterChain resourceServerSecurityFilterChain(HttpSecurity http) {
    http.securityMatcher("/api/**");
    http.oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults());
    ...
}

@Order(2)
SecurityFilterChain clientSecurityFilterChain(HttpSecurity http) {
    http.oauth2Login(...);
    ...
}

More OAuth2 background and complete configurations in my tutorials.

ch4mp
  • 6,622
  • 6
  • 29
  • 49
  • No: what you ask is a complete application or, at least, the answer to many questions that are not even asked. Follow the link to the tutorials, read carefully the introduction README and follow the tutorials matching your use-case. – ch4mp Jun 18 '23 at 10:04