Spring Boot - Keycloak: "failed to turn code into token" SSL

8/13/2019

I have spring boot with keycloak integration on kuberntes cluster. On production I certificate for SSL that is trusted for domain like "example.com". I configured my spring boot web application and keycloak to be under the same domain routing with ingress and providing SSL to reuse my certificate for the both servers.

https://example.com -> Spring boot https://example.com/auth -> Keycloak

This works fine but when I try to obtain a token from my web application through the keycloak spring adapter, I receive the following error in the logs:

message:  "failed to turn code into token"   
  stack_trace:  "s.s.p.c.SunCertPathBuilderException: unable to find valid certification path to requested target
    at s.s.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
    at s.s.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392)
    ... 95 common frames omitted
Wrapped by: s.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:397)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)
    at sun.security.validator.Validator.validate(Validator.java:262)
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:330)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:237)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1621)
    ... 89 common frames omitted
Wrapped by: 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)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
    at o.apache.http.conn.ssl.SSLSocketFactory.createLayeredSocket(SSLSocketFactory.java:570)
    at o.keycloak.adapters.SniSSLSocketFactory.createLayeredSocket(SniSSLSocketFactory.java:114)
    at o.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:554)
    at o.keycloak.adapters.SniSSLSocketFactory.connectSocket(SniSSLSocketFactory.java:109)
    at o.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:415)
    at o.a.h.i.c.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
    at o.a.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:144)
    at o.a.h.i.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:134)
    at o.a.h.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:605)
    at o.a.h.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:440)
    at o.a.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:835)
    at o.a.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at o.a.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
    at o.a.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
    at org.keycloak.adapters.ServerRequest.invokeAccessCodeToToken(ServerRequest.java:111)
    at o.k.adapters.OAuthRequestAuthenticator.resolveCode(OAuthRequestAuthenticator.java:335)
    at o.k.adapters.OAuthRequestAuthenticator.authenticate(OAuthRequestAuthenticator.java:280)
    at o.keycloak.adapters.RequestAuthenticator.authenticate(RequestAuthenticator.java:139)
    at o.k.a.s.f.KeycloakAuthenticationProcessingFilter.attemptAuthentication(KeycloakAuthenticationProcessingFilter.java:150)
    at o.s.s.w.a.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212)
    at o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at o.s.s.w.a.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    at o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at o.k.a.s.f.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:86)
    at o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at o.s.s.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74)
    at o.s.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    at o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at o.s.s.w.c.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at o.s.s.w.c.r.a.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at o.s.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    at o.s.s.w.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at o.s.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    at o.s.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at o.s.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
    at o.s.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
    at o.a.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at o.a.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at o.s.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at o.s.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    at o.a.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at o.a.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at o.s.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
    at o.s.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
    at o.a.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at o.a.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at o.s.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    ... 34 frames truncated
"   

Requests

-- drage503
keycloak
kubernetes
kubernetes-ingress
spring
spring-boot

1 Answer

8/26/2019

This error is because the trustore used to validate the TLS connection in your jvm doesn't trust the certificate you use for the keycloak server. Thus the request to turn the code into a token is never completed.

You need to add the CA certificate in your jvm trustore

As you are in a kubernetes environment, a easier way may be to use the facilities given by keycloak adapters (https://www.keycloak.org/docs/latest/securing_apps/index.html#_java_adapter_config):

  • trustore: to use a specific trustore to connect to keycloak
  • disable-trust-manager: to disable certificate verification (only for test)
-- Cédric Couralet
Source: StackOverflow