I have a grails 1.3.7 application that makes an https api call to a third party using the apache HttpClient. The third party URL I'm hitting has a valid certificate. I create and execute my request like so:
HttpClient client = new DefaultHttpClient()
List<BasicNameValuePair> queryParams = new ArrayList<BasicNameValuePair>()
queryParams.add(new BasicNameValuePair("a_parameter", "a_parameter_value"))
URI uri = URIUtils.createURI("https", "third.party.address", 443, "/some/url/for/us", URLEncodedUtils.format(queryParams, "UTF-8"), null)
HttpGet httpGet = new HttpGet(uri)
try {
log.debug "Sending request to ${uri}"
return client.execute(httpGet)
} catch(HttpException e) {
log.error "HttpException during location lookup request: ${e}"
return
} catch(IOException e) {
log.error "IOException during location lookup request: ${e}"
return
}
This works fine when I'm running my project in dev mode. I'm also able to directly call the same URL from curl and my browser with no errors. However, once my project is built into a war file and put on a tomcat instance that has a certificate/keystore defined so that clients can connect to US using https, my requests start failing with the following IOException:
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
I'm trying to figure out the point of failure here.
Why is making an https request from curl or my dev mode different than making an https request from an https configured tomcat instance?
The tomcat instance is not publicly accessible, but there are no certificate issues when I connect to it from my browser (chrome says the cert is fine, as does a verbose curl request).
I'm not an https/ssl expert by any stretch, so I'm looking for help explaining what is wrong, why it's wrong, and how I can fix it. I can provide any other needed info.
---Update---
I enabled the javax.net.debug
as suggested below and the output included the following error:
java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be\
non-empty
My googling has made me think that this issue is because I'm using the following java opt when starting tomcat:
-Djavax.net.ssl.trustStore=/path/to/tomcat/conf/myStore.jks
If that's true, how can I add the things I needed in myStore.jks and not override the defaults so everyone is happy?
The solution for me ended up being that we were overriding the default java trust store with our own with the java opt. This caused the cert sent by the third party to appear to be invalid since we didn't have any of the default root certs in our myStore.jks.
By adding our self-signed cert into the default java one (/lib/security/cacerts) and removing the java opt, everything was fine.
An alternative would be to add everything in the default java store into your custom store and still use the java opt. Whichever you find more maintainable for your situation.
I have seen this error so many times. I have used the following utility to grab a cert from a site that uses SSL. Go here and grab InstallCert. Compile and Run this utility. You can use the file which was generated by this utility as a keystore.
javax.net.debug
property - see http://www.herongyang.com/JDK/SSL-Socket-Communication-Debug-javax-net-debug.htm - Chris White 2012-04-06 02:00