Trusting SSL certificates: how does Commons HTTP client trust more than standard Java?

307 views Asked by At

To validate a JWT, I'm using jose4j to get certificate from an url, in this case, from google:

    HttpsJwks httpsJkws = new HttpsJwks("https://www.googleapis.com/oauth2/v3/certs");
    HttpsJwksVerificationKeyResolver httpsJwksKeyResolver = new HttpsJwksVerificationKeyResolver(httpsJkws);
    //httpsJkws.setSimpleHttpGet(simpleHttpGet);
    JwtConsumer jwtConsumer = new JwtConsumerBuilder()
            .setVerificationKeyResolver(httpsJwksKeyResolver)
            .build(); // create the JwtConsumer instance

However, this gets me a certificate error:

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Ok yes, I could add it to the JVM's trustore with some script, but I don't want to (as basically, it's not a self-signed certificate, and work just fine via a regular browser). Most of the time, I use Apache HTTP client 4.x, and for some reason, there, the call does work without issues:

    try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
        HttpResponse httpResponse = httpClient.execute(new HttpGet("https://www.googleapis.com/oauth2/v3/certs"));
        String response = (httpResponse.getEntity() != null) ? EntityUtils.toString(httpResponse.getEntity()) : null;
        log.debug(response);
    } catch (IOException e) {
        log.error("I/O Error when retrieving content from '" + jwksEndpointUrl + "': " + e.getMessage());
    }

I also tried with vanilla java, like new URL(jwksEndpointUrl).openStream(), and here I get the same certificate issue.

So, what does Apache HttpComponents client do differently, and how can I achieve the same for a standard Java HTTP GET of via jose4j?

1

There are 1 answers

0
Bruce T. On

Liberty's behavior until recently was to not trust anything by default, so even well known certificates like the one from Google have to be added to it's truststore to avoid the error you are seeing.

In more recent versions, (190012+ ?) one can set "trustDefaultCerts=true", then it behaves more like a browser and trusts certificates from well-known issuers like Google by default. Here's an example snippet from server.xml:

<keyStore id="defaultKeyStore" password="keyspass" /> <ssl id="defaultSSLConfig" keyStoreRef="defaultKeyStore" trustDefaultCerts="true"/>