<p>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.</p>

<p><a href="https://example.com" rel="nofollow noreferrer">https://example.com</a> -> Spring boot
<a href="https://example.com/auth" rel="nofollow noreferrer">https://example.com/auth</a> -> Keycloak</p>

<p>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:</p>

<pre><code>message:  "failed to turn code into token"   
</code></pre>

<pre><code>  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
"   
</code></pre>

<p><a href="https://i.stack.imgur.com/HBxDs.png" rel="nofollow noreferrer">Requests</a></p>

drage503
<p>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.</p>

<p>You need to <a href="https://access.redhat.com/documentation/en-us/red_hat_jboss_data_virtualization/6.2/html/security_guide/add_a_certificate_to_a_truststore_using_keytool" rel="nofollow noreferrer">add the CA certificate in your jvm trustore</a></p>

<p>As you are in a kubernetes environment, a easier way may be to use the facilities given by keycloak adapters (<a href="https://www.keycloak.org/docs/latest/securing_apps/index.html#_java_adapter_config" rel="nofollow noreferrer">https://www.keycloak.org/docs/latest/securing_apps/index.html#_java_adapter_config</a>): </p>

<ul>
<li>trustore: to use a specific trustore to connect to keycloak</li>
<li>disable-trust-manager: to disable certificate verification (only for test)</li>
</ul>
