Search code examples
javarestsecuritysslx509trustmanager

Suppressing SSL certificate validations in java gives 502 cannot connect. Works perfectly fine with curl (with -k option) and Postman (SSL disabled))


I am trying to hit an SSL enabled Rest API by disabling the SSL certificate checks as follows;

            TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[0];
                    }
                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                    }
                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    }
                }
            };
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            SSLContext.setDefault(sc);
            HostnameVerifier allHostsValid = new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };
            String auth = "<<username>>:<<password>>";
            byte[] authBytes = auth.getBytes(StandardCharsets.UTF_8);
            String encodedAuth = Base64.getEncoder().encodeToString(authBytes);
            String url = "myURLHere";
            Client client = ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier(allHostsValid).build();
            String input = "myJsonHere";
            Response response = client
               .target(url)
               .request()
               .header("Authorization", "Basic " + encodedAuth)
               .post(Entity.json(input));

Refer : https://stackoverflow.com/a/27398820/11226302

However, I am getting the following response;

InboundJaxrsResponse{context=ClientResponse{method=POST, uri=myURLHere, status=502, reason=cannotconnect}}

I also tried the similar logic using HttpsURLConnection.
Refer: https://stackoverflow.com/a/876785/11226302

Getting a similar error as below;

java.lang.RuntimeException: Failed : HTTP error code : 502cannotconnect

I need to do this for testing purposes, but am unable to proceed now.

I am able to get the right response using curl and Postman Client (as mentioned in the Title of this Question) Can anyone suggest what could be going wrong here?

I am using java 8

FYI, the production will have the certificate set up. I am doing this insecure configuration so that I may be able to call this Rest API from my local set up.


Solution

  • A 502 error indicates that you were able to connect successfully to a TLS protected endpoint (possibly by ignoring its untrustworthy certificate). What has gone wrong is that this endpoint is failing to proxy the connection to another host, and it is the proxy that "cannot connect".

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502

    It follows that you must be suffering from a configuration issue specific to your java process that does not affect curl or postman. An example i've seen would be where you are attempting to access a webservices endpoint on localhost in windows, but due to OS and office LAN settings the connection is sent to the networks' internet proxy first - which doesn't know what to do with the address '127.0.0.1'. I'd check your OS network settings are set appropriatly, and that the environment variables that can be used to override them in a java process are not set:

    https.proxyHost
    https.proxyPort
    http.nonProxyHosts
    

    Local programs like Fiddler might also be attempting to act as a proxy and contributing to the issue.

    Another possibility is that your counterparty is using a reverse proxy at their end, which is struggling to route the request issued by the java process for some reason. Make sure you are using exactly the same hostname with the java client as you used with curl/postman (not a manually resolved IP address or local DNS alias).

    An aside: hacking in a no-op trustmanager while prototyping is something many Java developers will have done at one point or another - but it is a much better practise to add the certificate you wish to trust to your local JVM truststore, or a process specific truststore instead. That way you don't have to use different code in testing and production.

    https://docs.oracle.com/cd/E79792_01/resa/pdf/141/html/merch_sg/apps-chapter%207.htm#CHDJBIJD