I have two Docker containers:
- RedHat Keycloak Server (https://keycloak.some.domain.com)
- Springboot app (http://localhost:8081)
In my Springboot app, I have defined a secure page at: http://localhost:8081/api/sample.json
Now, when I hit that endpoint, I am redirected to the correct login page and, if I submit the correct login/password credentials, I get the following 403 error (forbidden) page:
However, if I run the Springboot app directly, without a docker wrapper, like this:
java -jar app.jar
then, when I hit the same protected endpoint, I am redirected to the correct login page and, if I submit the correct login/password credentials, in this case, I get the CORRECT, expected page/response !!! (it is the same app !!!)
Given this scenario, I have started the dockerized Springboot app, went inside of the container with:
docker exec -it app bash
and then intalled lynx like this:
apt-get install lynx
from there, I did hit the protected endpoint locally:
lynx http://localhost:8081/api/sample.json
But I got exactly the same error page (403) error. So, I believe the problem is the docker wrapper, not the app. That is critical, because it means that this kind of behavior between keycloak and ANY dockerized app will be similar. :(
As a conclusion, if I execute "docker run -d -p 8081:8081 springboot-app-image", everything works perfectly except authentication process against keycloak (outside and inside the container).
From the Springboot app logs I can see this error trace when I hit the dockerized endpoint:
2020-03-17 15:29:19.503 INFO 1 --- [ main] com.example.app.MainApp : Started MainApp in 13.257 seconds (JVM running for 14.845)
2020-03-17 15:29:30.139 DEBUG 1 --- [nio-8081-exec-1] o.k.adapters.PreAuthActionsHandler : adminRequest http://localhost:8081/api/sample2.json
2020-03-17 15:29:30.169 DEBUG 1 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Using provider 'secret' for authentication of client 'login-app'
2020-03-17 15:29:30.176 DEBUG 1 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Loaded clientCredentialsProvider secret
2020-03-17 15:29:30.179 DEBUG 1 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Loaded clientCredentialsProvider jwt
2020-03-17 15:29:30.182 DEBUG 1 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Loaded clientCredentialsProvider secret-jwt
2020-03-17 15:29:30.184 DEBUG 1 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Loaded clientCredentialsProvider secret
2020-03-17 15:29:30.185 DEBUG 1 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Loaded clientCredentialsProvider jwt
2020-03-17 15:29:30.188 DEBUG 1 --- [nio-8081-exec-1] o.k.a.a.ClientCredentialsProviderUtils : Loaded clientCredentialsProvider secret-jwt
2020-03-17 15:29:30.457 DEBUG 1 --- [nio-8081-exec-1] o.keycloak.adapters.KeycloakDeployment : resolveUrls
2020-03-17 15:29:30.461 DEBUG 1 --- [nio-8081-exec-1] o.k.adapters.KeycloakDeploymentBuilder : Use authServerUrl: https://keycloak.some.domain.com/auth, tokenUrl: https://keycloak.ci.ultrasist.net/auth/realms/SpringBootKeycloak/protocol/openid-connect/token, relativeUrls: NEVER
2020-03-17 15:29:30.479 DEBUG 1 --- [nio-8081-exec-1] .k.a.t.AbstractAuthenticatedActionsValve : AuthenticatedActionsValve.invoke /api/sample2.json
2020-03-17 15:29:30.481 DEBUG 1 --- [nio-8081-exec-1] o.k.a.AuthenticatedActionsHandler : AuthenticatedActionsValve.invoke http://localhost:8081/api/sample2.json
2020-03-17 15:29:30.483 DEBUG 1 --- [nio-8081-exec-1] o.k.a.AuthenticatedActionsHandler : Policy enforcement is disabled.
2020-03-17 15:29:30.494 INFO 1 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-03-17 15:29:30.495 INFO 1 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-03-17 15:29:30.526 INFO 1 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 29 ms
2020-03-17 15:29:30.592 DEBUG 1 --- [nio-8081-exec-1] o.k.adapters.PreAuthActionsHandler : adminRequest http://localhost:8081/api/sample2.json
2020-03-17 15:29:30.694 DEBUG 1 --- [nio-8081-exec-1] o.k.a.s.management.HttpSessionManager : Session created: E9F1974D7E734867356A0366CC0AC52A
2020-03-17 15:29:30.705 DEBUG 1 --- [nio-8081-exec-1] k.a.s.a.KeycloakAuthenticationEntryPoint : Redirecting to login URI /sso/login
2020-03-17 15:29:30.731 DEBUG 1 --- [nio-8081-exec-3] o.k.adapters.PreAuthActionsHandler : adminRequest http://localhost:8081/sso/login
2020-03-17 15:29:30.735 DEBUG 1 --- [nio-8081-exec-3] .k.a.t.AbstractAuthenticatedActionsValve : AuthenticatedActionsValve.invoke /sso/login
2020-03-17 15:29:30.737 DEBUG 1 --- [nio-8081-exec-3] o.k.a.AuthenticatedActionsHandler : AuthenticatedActionsValve.invoke http://localhost:8081/sso/login
2020-03-17 15:29:30.739 DEBUG 1 --- [nio-8081-exec-3] o.k.a.AuthenticatedActionsHandler : Policy enforcement is disabled.
2020-03-17 15:29:30.757 DEBUG 1 --- [nio-8081-exec-3] o.k.adapters.PreAuthActionsHandler : adminRequest http://localhost:8081/sso/login
2020-03-17 15:29:30.764 DEBUG 1 --- [nio-8081-exec-3] f.KeycloakAuthenticationProcessingFilter : Request is to process authentication
2020-03-17 15:29:30.766 DEBUG 1 --- [nio-8081-exec-3] f.KeycloakAuthenticationProcessingFilter : Attempting Keycloak authentication
2020-03-17 15:29:30.795 DEBUG 1 --- [nio-8081-exec-3] o.k.a.s.token.SpringSecurityTokenStore : Checking if org.keycloak.adapters.springsecurity.authentication.SpringSecurityRequestAuthenticator@1273c136 is cached
2020-03-17 15:29:30.800 DEBUG 1 --- [nio-8081-exec-3] o.k.adapters.OAuthRequestAuthenticator : there was no code
2020-03-17 15:29:30.805 DEBUG 1 --- [nio-8081-exec-3] o.k.adapters.OAuthRequestAuthenticator : redirecting to auth server
2020-03-17 15:29:30.809 DEBUG 1 --- [nio-8081-exec-3] o.k.adapters.OAuthRequestAuthenticator : callback uri: http://localhost:8081/sso/login
2020-03-17 15:29:30.822 DEBUG 1 --- [nio-8081-exec-3] f.KeycloakAuthenticationProcessingFilter : Auth outcome: NOT_ATTEMPTED
2020-03-17 15:29:30.824 DEBUG 1 --- [nio-8081-exec-3] o.k.adapters.OAuthRequestAuthenticator : Sending redirect to login page: https://keycloak.some.domain.com/auth/realms/SpringBootKeycloak/protocol/openid-connect/auth?response_type=code&client_id=login-app&redirect_uri=http%3A%2F%2Flocalhost%3A8081%2Fsso%2Flogin&state=412c7a6f-720f-4eea-b825-209c76d3a3db&login=true&scope=openid
2020-03-17 15:29:34.680 DEBUG 1 --- [nio-8081-exec-4] o.k.adapters.PreAuthActionsHandler : adminRequest http://localhost:8081/sso/login?state=412c7a6f-720f-4eea-b825-209c76d3a3db&session_state=802e466d-7b1e-4180-8870-cdae07b2fbae&code=7d93b2cf-d72b-4e83-b219-19d48897c9b7.802e466d-7b1e-4180-8870-cdae07b2fbae.35bc9442-2e19-485a-afad-adc1e62b4c52
2020-03-17 15:29:34.687 DEBUG 1 --- [nio-8081-exec-4] .k.a.t.AbstractAuthenticatedActionsValve : AuthenticatedActionsValve.invoke /sso/login
2020-03-17 15:29:34.688 DEBUG 1 --- [nio-8081-exec-4] o.k.a.AuthenticatedActionsHandler : AuthenticatedActionsValve.invoke http://localhost:8081/sso/login?state=412c7a6f-720f-4eea-b825-209c76d3a3db&session_state=802e466d-7b1e-4180-8870-cdae07b2fbae&code=7d93b2cf-d72b-4e83-b219-19d48897c9b7.802e466d-7b1e-4180-8870-cdae07b2fbae.35bc9442-2e19-485a-afad-adc1e62b4c52
2020-03-17 15:29:34.691 DEBUG 1 --- [nio-8081-exec-4] o.k.a.AuthenticatedActionsHandler : Policy enforcement is disabled.
2020-03-17 15:29:34.694 DEBUG 1 --- [nio-8081-exec-4] o.k.adapters.PreAuthActionsHandler : adminRequest http://localhost:8081/sso/login?state=412c7a6f-720f-4eea-b825-209c76d3a3db&session_state=802e466d-7b1e-4180-8870-cdae07b2fbae&code=7d93b2cf-d72b-4e83-b219-19d48897c9b7.802e466d-7b1e-4180-8870-cdae07b2fbae.35bc9442-2e19-485a-afad-adc1e62b4c52
2020-03-17 15:29:34.701 DEBUG 1 --- [nio-8081-exec-4] f.KeycloakAuthenticationProcessingFilter : Request is to process authentication
2020-03-17 15:29:34.703 DEBUG 1 --- [nio-8081-exec-4] f.KeycloakAuthenticationProcessingFilter : Attempting Keycloak authentication
2020-03-17 15:29:34.711 DEBUG 1 --- [nio-8081-exec-4] o.k.a.s.token.SpringSecurityTokenStore : Checking if org.keycloak.adapters.springsecurity.authentication.SpringSecurityRequestAuthenticator@4c5ab508 is cached
2020-03-17 15:29:34.712 DEBUG 1 --- [nio-8081-exec-4] o.k.adapters.OAuthRequestAuthenticator : there was a code, resolving
2020-03-17 15:29:34.712 DEBUG 1 --- [nio-8081-exec-4] o.k.adapters.OAuthRequestAuthenticator : checking state cookie for after code
2020-03-17 15:29:34.715 DEBUG 1 --- [nio-8081-exec-4] o.k.adapters.OAuthRequestAuthenticator : ** reseting application state cookie
2020-03-17 15:29:35.365 ERROR 1 --- [nio-8081-exec-4] o.k.adapters.OAuthRequestAuthenticator : failed to turn code into token
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[na:1.8.0_65]
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) ~[na:1.8.0_65]
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302) ~[na:1.8.0_65]
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) ~[na:1.8.0_65]
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509) ~[na:1.8.0_65]
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) ~[na:1.8.0_65]
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979) ~[na:1.8.0_65]
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914) ~[na:1.8.0_65]
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062) ~[na:1.8.0_65]
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) ~[na:1.8.0_65]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) ~[na:1.8.0_65]
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) ~[na:1.8.0_65]
at org.apache.http.conn.ssl.SSLSocketFactory.createLayeredSocket(SSLSocketFactory.java:570) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.keycloak.adapters.SniSSLSocketFactory.createLayeredSocket(SniSSLSocketFactory.java:114) ~[keycloak-adapter-core-4.8.3.Final.jar!/:4.8.3.Final]
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:554) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.keycloak.adapters.SniSSLSocketFactory.connectSocket(SniSSLSocketFactory.java:109) ~[keycloak-adapter-core-4.8.3.Final.jar!/:4.8.3.Final]
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:415) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:144) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:134) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:605) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:440) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:835) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) ~[httpclient-4.5.8.jar!/:4.5.8]
at org.keycloak.adapters.ServerRequest.invokeAccessCodeToToken(ServerRequest.java:111) ~[keycloak-adapter-core-4.8.3.Final.jar!/:4.8.3.Final]
at org.keycloak.adapters.OAuthRequestAuthenticator.resolveCode(OAuthRequestAuthenticator.java:335) [keycloak-adapter-core-4.8.3.Final.jar!/:4.8.3.Final]
at org.keycloak.adapters.OAuthRequestAuthenticator.authenticate(OAuthRequestAuthenticator.java:280) [keycloak-adapter-core-4.8.3.Final.jar!/:4.8.3.Final]
at org.keycloak.adapters.RequestAuthenticator.authenticate(RequestAuthenticator.java:139) [keycloak-adapter-core-4.8.3.Final.jar!/:4.8.3.Final]
at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.attemptAuthentication(KeycloakAuthenticationProcessingFilter.java:149) [keycloak-spring-security-adapter-4.8.3.Final.jar!/:4.8.3.Final]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:86) [keycloak-spring-security-adapter-4.8.3.Final.jar!/:4.8.3.Final]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.1.6.RELEASE.jar!/:5.1.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67) [spring-boot-container-bundle-4.8.3.Final.jar!/:4.8.3.Final]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181) [spring-boot-container-bundle-4.8.3.Final.jar!/:4.8.3.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_65]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_65]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.17.jar!/:9.0.17]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_65]
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387) ~[na:1.8.0_65]
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) ~[na:1.8.0_65]
at sun.security.validator.Validator.validate(Validator.java:260) ~[na:1.8.0_65]
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) ~[na:1.8.0_65]
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) ~[na:1.8.0_65]
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) ~[na:1.8.0_65]
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491) ~[na:1.8.0_65]
... 87 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:146) ~[na:1.8.0_65]
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131) ~[na:1.8.0_65]
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) ~[na:1.8.0_65]
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382) ~[na:1.8.0_65]
... 93 common frames omitted
2020-03-17 15:29:35.373 DEBUG 1 --- [nio-8081-exec-4] f.KeycloakAuthenticationProcessingFilter : Auth outcome: FAILED
2020-03-17 15:29:35.377 DEBUG 1 --- [nio-8081-exec-4] f.KeycloakAuthenticationProcessingFilter : Authentication request failed: org.keycloak.adapters.springsecurity.KeycloakAuthenticationException: Invalid authorization header, see WWW-Authenticate header for details
org.keycloak.adapters.springsecurity.KeycloakAuthenticationException: Invalid authorization header, see WWW-Authenticate header for details
at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.attemptAuthentication(KeycloakAuthenticationProcessingFilter.java:157) ~[keycloak-spring-security-adapter-4.8.3.Final.jar!/:4.8.3.Final]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
In the last error trace, I am able to see something about SSL handshake error, and other error mesage saying:
Invalid authorization header, see WWW-Authenticate header for details
but... Why this error is not present when I run the java app directly, without a docker container?
I have found some references but they are not useful for my problem:
- Keycloak secure app in container
- Docker (Spring Boot or Thorntail) and Keycloak
- Spring Boot Application using Keycloak, single sign on doesn't work behind an Apache Web Server
This is my Spring boot configuration class for keycloak that is part of the code that work perfectly outside the docker container but NOT inside a docker container:
@KeycloakConfiguration
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Bean
@Primary
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.cors().and().csrf().disable();
http.authorizeRequests()
.antMatchers("/api/sample*").hasRole("user")
.antMatchers("/ui/second*").hasRole("user")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
}
And, this is the config for keycloak:
And, this is my Dockerfile were bad behavior is detected:
FROM openjdk:8
COPY app.jar /deploy/app.jar
WORKDIR /deploy
CMD java -jar app.jar
It is built by doing:
docker build . -t example
And it is executed like this:
docker run -d -p 8081:8081 example
You can see that in the last way, the security is not working properly.
Now, I have to say that, in a direct way it works great:
java -jar app.jar
So, my obviouse question (to the jboss guys or RedHat guys or any guy with the enought wisdom) is, How can I make it work Keycloak Server from within a containerized Springboot application?