javakeycloakkeystorepkix

Embedded Keycloak (Spring boot Java) certificate issue: Unable to resolve the Configuration with the provided Issuer


Currently i am building a web app with Angular frontend and Java backend. At this moment i am implementing keycloak as an embedded spring boot app with the help of Baeldung tutorial (https://www.baeldung.com/keycloak-embedded-in-spring-boot-app). My java backend is the resource server. All my requests were succesfully authenticated with keycloak and oauth openid until my localhost certificate expired.

I have generated a new self signed certificate with keytool with following settings: `

"C:\Program Files\Git\usr\bin\openssl.exe" req -new -x509 -newkey rsa:2048 -sha256 -nodes -keyout localhost.key -days 3560 -out localhost.crt -config sslconf.conf`

and following configuration:

default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = v3_req
distinguished_name = dn

[dn]
C = NL
ST = Netherlands
L = Netherlands
O = DMT
OU = My Organisational Unit
emailAddress = xx@xx.nl
CN = localhost

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost

This certificate is used in the following places:

I have imported the new certificate and keystore by following statement: "C:\Program Files\Git\usr\bin\openssl.exe" pkcs12 -export -in C:\DMT\sources\code\multi\localhost.crt -inkey C:\DMT\sources\code\multi\localhost.key -name localhost_dmt -out dmt-keystore.p12

this keystore is referred by the java properties file of both the keycloak embedded java server and the backend java server itself.

After restarting everything the browser has accepted the new certificate and both the backend and keycloak are running with SLL and valid and same certificate.

All seems fine, however when i perform a request to the resource server the request fails during authentication with openid configuration: `

Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://localhost:8083/auth/realms/dmt/.well-known/openid-configuration": PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:670) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.security.oauth2.jwt.JwtDecoderProviderConfigurationUtils.getConfiguration(JwtDecoderProviderConfigurationUtils.java:132) ~[spring-security-oauth2-jose-5.5.1.jar:5.5.1]
    ... 66 common frames omitted
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:369) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:312) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:307) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1357) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1232) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1175) ~[na:na]
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392) ~[na:na]
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:478) ~[na:na]
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:456) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:199) ~[na:na]
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1369) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1278) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:401) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:373) ~[na:na]
    at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:567) ~[na:na]
    at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:197) ~[na:na]
    at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:168) ~[na:na]
    at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:776) ~[spring-web-5.3.8.jar:5.3.8]
    ... 68 common frames omitted
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 java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439) ~[na:na]
    at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306) ~[na:na]
    at java.base/sun.security.validator.Validator.validate(Validator.java:264) ~[na:na]
    at java.base/sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:313) ~[na:na]
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:222) ~[na:na]
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:129) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1341) ~[na:na]
    ... 86 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) ~[na:na]
    at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) ~[na:na]
    at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297) ~[na:na]
    at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434) ~[na:na]
    ... 92 common frames omitted

` I cant figure out why keycloak does not authenticate anymore. As before replacing the old certificate everything worked fine. It must be that keycloak need to know the new certificate somehow, but i cant find out where to put it then. Tried to find it in documentation but did not succeed unfortunately. It is also a bit more complicated as i am using an embedded keycloak in java spring boot. I would assume the the custom keystore provided in the java properties file would be sufficient.

properties file keycloak embedded:

server:
  port: 8083
  ssl:
    key-store: "C:\\DMT\\sources\\code\\multi\\dmt-keystore.p12"
    key-store-password: passwordkeystore
    key-store-type: pkcs12
    key-alias: localhost_dmt
    key-password: password
    enabled: true

Solution

  • I think you forgot to import it as trusted certificate in your JRE cacerts file.

    You can have a look at what I do in this repo. If you browse the script source, you'll see how to import the new certificate in cacerts around line 178. You can also run this script with git bash, it will print the command (refer to Readme for pre-requisites).