How to Resolve Java HTTPS Exceptions
TLDR: Most java HTTPS connection problems can be fixed by updating the JVM. Don't import into cacerts unless you really need to (eg you have an internal CA within your organization). Test other http clients to make sure it is really a java problem.
Before we get into all the details I'll start off by saying that the old advice to import the domain's certificate into cacerts is almost always the wrong way to fix this problem. Just because it may work doesn't mean it is a good solution. By importing a certificate into the
cacerts keystore file you are telling java that this certificate is a trusted certificate authority. A certificate authority is allowed to sign certificates for any domain and java may then trust those certificates. Further as trusted CA certs become compromised they are revoked and should be removed from the cacerts file, the entire system of trust gets eroded if this file is not kept up to date.
Test Other HTTP Clients
Before you get too far down the rabbit hole you should make sure that you are indeed dealing with a java problem. Try connecting to the server using other http clients such as a web browser, curl, wget, powershell, etc.
The PKIX path validation failed exception is a pretty common java exception you may get when attempting to connect to a HTTPS server or some other protocol that uses TLS (formerly known as SSL). Here are some common causes:
Certificate is Expired
The certificate for the domain you are trying to connect to has expired. There is not much you can unless you operate the domain - the certificate needs to be renewed. Also make sure your server clock has the correct time.
I recently helped someone that was having this issue and it was due to a hosts file entry pointing to an old server, once the certificate expired it started causing a problem, but it was not clear because it worked everywhere except for the server in question.
Invalid Certificate Chain, Missing Intermediate Certificate
It is pretty common for site operators to forget to specify the intermediate certificate when they setup HTTPS. Several years ago Certificate authorities (CA) would sign certificates directly off of their root certificate. These days must CA's use an intermediate certificate, so they sign a sub CA certificate which then signs certificates for their customers. This approach allows the CA to revoke an intermediate certificate if it becomes compromised but they can just generate a new intermediate off the very valuable root certificate.
This site: What is my cert chain? is really good at debugging, and explaining in more detail.
This problem can be frustrating because the site will still work on most browsers, but will fail when you try to connect to it. This is because browsers cache intermediate trusted certificates and trust them for future requests.
You might get unable to find valid certification path to requested target in your exception with this issue.
Domain uses a new Certificate Authority Cert
The Certificate Authority may have a new certificate that is not in the
cacerts file. You will find hundreds of articles online telling you to just import the certificate into Java's cacerts keystore file. The best way to fix this is to update the jvm, when new versions of the jvm are released the cacerts file is often updated with the latest trusted certs. You might be able to grab the cacerts file from the latest jvm and use that if you don't want to update the JVM, but updating the JVM should be something you do frequently to stay up to date with security patches (security updates for the JVM are usually released on a quarterly basis). You can also generate a cacerts file using Mozilla's Certificate Authority List.
If you are using an internal certificate authority then you should import your internal ca cert into the cacerts file. If you have to connect to a server using a self signed certificate you basically have two options: 1) Write a custom
javax.net.ssl.X509TrustManager to allow the self signed cert 2) import the self signed cert into cacerts (not ideal).
Another common type of HTTPS connection exception is: javax.net.ssl.SSLHandshakeException, this is usually due to an inability for the client (java) and the server to find a SSL / TLS protocol and cipher that they agree on.
Updating Java is usually the best resolution for this type of exception. For example if you are running on Java 1.6 or below TLS 1.2 is not supported. If you are on Java 7 (1.7), TLS 1.2 is supported but not enabled by default.
You can tell Java which protocols to use by default by setting the java system property
https.protocols=TLSv1.2 for example. You may find however that this doesn't always work, some java code or libraries may be coded to use a specific protocol that the server doesn't support (eg TLS 1.0). In that case you need to update the library or code.
- HackMyCF Adds SSL/TLS Scanner - May 27, 2015
- Using Mozilla's Certificate Authority List for Java SSL - June 6, 2014
- HTTP Strict Transport Security - September 17, 2010
- How To Scream Unsecured - May 2, 2006
- Secure Forms - January 27, 2006
- What is the difference between ASCII Chr(10) and Chr(13)
- Fixinator and Foundeo Security Bundle
- Running CFML on AWS Lambda with FuseLess Slides
- Updating Java on ColdFusion or Lucee
- ColdFusion returning empty response with server-error: true
- Careful applying CF11u16, CF2016u8, CF2018u2
- Sessions don't work in Chrome but do in IE
- csrfVerifyToken does not invalidate the token