59
public HttpClientVM() {

    BasicHttpParams params = new BasicHttpParams();
    ConnManagerParams.setMaxTotalConnections(params, 10);
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    HttpProtocolParams.setUseExpectContinue(params, false);
    HttpConnectionParams.setStaleCheckingEnabled(params, true);
    HttpConnectionParams.setConnectionTimeout(params, 30000);
    HostnameVerifier hostnameVerifier=
          org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
    HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
    SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
    socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http",socketFactory, 80));
    schemeRegistry.register(new Scheme("https",socketFactory, 443));
        ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, schemeRegistry);
        // Set verifier     
        client = new DefaultHttpClient(manager, params);    
    }

Problem:

When executing client.accessURL(url), the following error occurs:

Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
    at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:352)
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:397)
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:495)
    at org.apache.http.conn.scheme.SchemeSocketFactoryAdaptor.connectSocket(SchemeSocketFactoryAdaptor.java:62)
    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:148)
    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:150)
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121)
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:575)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:425)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)

Additional information:

  • Window 7
  • HttpClient 4
Rene Knop
  • 1,788
  • 3
  • 15
  • 27
Liu
  • 591
  • 1
  • 4
  • 3

12 Answers12

31

Expired certificate was the cause of our "javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated".

keytool -list -v -keystore filetruststore.ts

    Enter keystore password:
    Keystore type: JKS
    Keystore provider: SUN
    Your keystore contains 1 entry
    Alias name: somealias
    Creation date: Jul 26, 2012
    Entry type: PrivateKeyEntry
    Certificate chain length: 1
    Certificate[1]:
    Owner: CN=Unknown, OU=SomeOU, O="Some Company, Inc.", L=SomeCity, ST=GA, C=US
    Issuer: CN=Unknown, OU=SomeOU, O=Some Company, Inc.", L=SomeCity, ST=GA, C=US
    Serial number: 5011a47b
    Valid from: Thu Jul 26 16:11:39 EDT 2012 until: Wed Oct 24 16:11:39 EDT 2012
buzz3791
  • 1,683
  • 2
  • 20
  • 38
15

This exception will come in case your server is based on JDK 7 and your client is on JDK 6 and using SSL certificates. In JDK 7 sslv2hello message handshaking is disabled by default while in JDK 6 sslv2hello message handshaking is enabled. For this reason when your client trying to connect server then a sslv2hello message will be sent towards server and due to sslv2hello message disable you will get this exception. To solve this either you have to move your client to JDK 7 or you have to use 6u91 version of JDK. But to get this version of JDK you have to get the MOS (My Oracle Support) Enterprise support. This patch is not public.

Tanuj Kumar
  • 191
  • 1
  • 3
  • Had the same problem in Java 1.7, when I compiled and run it in 1.8 it in server it works fine. – Lucky Oct 31 '18 at 08:14
15

This error is because your server doesn't have a valid SSL certificate. Hence we need to tell the client to use a different TrustManager. Here is a sample code:

SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {

    public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
    }

    public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
    }

    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = base.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", 443, ssf));

client = new DefaultHttpClient(ccm, base.getParams());
Thunder
  • 2,994
  • 1
  • 24
  • 19
bnguyen82
  • 6,048
  • 5
  • 30
  • 39
  • 10
    How will removing the security from this end solve the problem at the other end? That TrustManager code doesn't even conform to the specification. – user207421 Mar 06 '12 at 05:30
  • I doesn't see your point. The problem comes from client side, hence we only need to change it. Which TrustManager code line does not comply with specification? – bnguyen82 Mar 06 '12 at 06:25
  • 8
    `getAcceptedIssuers()` is specified never to return null. The code you have posted is radically insecure. It doesn't solve any problem, it just creates another problem, for example vulnerability to man-in-the-middle attacks. – user207421 Mar 06 '12 at 07:29
  • 4
    The code is perfectly all right for testing purposes, but definitely is not suitable for production – yegor256 Nov 01 '12 at 11:08
  • Had to downvote this, because it removes the point of using mutual authentication at all. You might as well use plain HTTP instead of this (less hassle to implement anyway). – Jas May 22 '14 at 09:03
  • 1
    Thank you for this. Needed to do some testing while we sort out cert specifics, this helped keep the dev ball rolling. – DocWatson Jul 02 '14 at 15:14
6

You can get this if the client specifies "https" but the server is only running "http". So, the server isn't expecting to make a secure connection.

thebiggestlebowski
  • 2,610
  • 1
  • 33
  • 30
3

This can also happen if you are attempting to connect over HTTPS and the server is not configured to handle SSL connections correctly.

I would check your application servers SSL settings and make sure that the certification is configured correctly.

Casey
  • 12,070
  • 18
  • 71
  • 107
  • 10
    What can be configured wrong? The ssl certificate works fine in the browser. Why does it not work with Java? Why is Java so special? – Robert Reiz Aug 26 '13 at 21:48
2

In my case, the server was running on Docker (using base image adoptopenjdk/openjdk11:alpine) and the issue was a TLS protocol level error (thanks to the following page for providing the explanation: https://jfrog.com/knowledge-base/how-to-resolve-the-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-error-when-using-java-11/).

The solution was eventually to run the client using the following java flag:

-Djdk.tls.client.protocols=TLSv1.2
1

In my case I was using a JDK 8 client and the server was using insecure old ciphers. The server is Apache and I added this line to the Apache config:

SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:!MEDIUM:!LOW:!SSLv2:!EXPORT

You should use a tool like this to verify your SSL configuration is currently secure: https://www.ssllabs.com/ssltest/analyze.html

Sarel Botha
  • 12,419
  • 7
  • 54
  • 59
  • did this fix the error for you .. did you add the SSlCipherSuite property to property files. please elaborate – Tiny Sep 01 '20 at 09:14
  • I doubt I made any changes to the client. I think I only changed the ciphers on the server and it fixed it. – Sarel Botha Sep 02 '20 at 14:24
1

If user Java 11.0.2 AdoptOpenJDK, may the bug, see jfrog article:

ARTIFACTORY: How to Resolve the javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated Error When Using Java 11

Victor Lv
  • 81
  • 4
0

The same issue I was facing we are using VPN this occurs when the captcha certificate is missing in your keystore.jks file.

  1. Check if your server keystore has the captcha certificate or not, to do this use the below command. Go to your keystore.jks location and hit usr/java/jdk1.7.0_91/bin/keytool -list -v -keystore keystore.jks it will list all the certificate you have in it where : usr/java/jdk1.7.0_91/bin/keytool is the location of your java keytool you can use which javacommand if you are not sure of java path on your server.

  2. If its not there then you have to download the captcha certifacte and install it to keystore, to do this follow the step:

a. Open : https://www.google.com/recaptcha/api/siteverify and click on the secure icon,Click on certificate is valid

enter image description here

b. Click on connection is secure

enter image description here

c. After that Click on details and export the certificate as .crt enter image description here

d. Copy this .crt file on your server. enter image description here

Go to the location of keystore.jks : 
Run this command : 
 /usr/java/jdk1.7.0_91/bin/keytool -import -alias googlecaptcha -keystore "/location/to/the/keystore.jks" -file "/location/to/crtfile/where/you/have/keep/ /on/server/googlecaptcha.crt"

NOTE : I have renamed www.google.com.crt as googlecaptcha.crt, also change the location parameter.

Once the certificate is installed you can use the list command (given in step 1) to verify it.

Here is the code snippet once the above process is done :

try {
          URL url = new URL(googleURL);
          if(proxy!=null){
              conn = (HttpURLConnection)url.openConnection(proxy);
          }else{
              conn = (HttpURLConnection)url.openConnection();
          }
          conn.setRequestMethod("POST");
          conn.setRequestProperty("Accept", "application/json");
            
          InputStreamReader in = new InputStreamReader(conn.getInputStream());
          BufferedReader br = new BufferedReader(in);
          StringBuilder sb = new StringBuilder();
          String output;
          while ((output = br.readLine()) != null) {
            System.out.println(output);
            sb.append(output);
          } 
          String responseNew = sb.toString();
           responseObject = (ImplValidateCaptchaGoogleResponse)this.mapper.readValue(responseNew, ImplValidateCaptchaGoogleResponse.class);
        
        } catch (Exception e) {
        LOGGER.debug("ERROR_OCCURED ::"+e.getMessage() );
          e.printStackTrace();
        } 
}
0

This is issue of Certificate that you created on system. You need to specify the IP while create certificate [Keystore] Please refer command.

keytool -genkeypair -alias baeldung -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore baeldung.p12 -validity 36500 -ext "SAN:c=DNS:<localhost/Server DNSName>,IP:"

Rajeev Rathor
  • 1,830
  • 25
  • 20
0

Spring application and "peer not authenticated" error

If you are experiencing this error while connecting to your Spring application, check the security configuration (@EnableWebSecurity, WebSecurityConfigurerAdapter, etc., based on what approach you use). If you secure the application's endpoints, make sure that you either add the target endpoint to exclusions (and do not require authentication) or ensure the proper authentication while trying to connect using the strategy that is set up in your application.

In my case, I was trying to connect to the application using WebSocket (with TLS support). I had this snippet in the security configuration (it's in Kotlin, but you will be able to get the idea):

@Bean
fun filterChain(http: HttpSecurity): SecurityFilterChain {
    http.csrf {
        it.disable()
    }.authorizeHttpRequests {
        it
            .requestMatchers(PUT, "/tasks/**").hasAuthority("<scope1>")
            .requestMatchers(POST, "/tasks").hasAuthority("<scope2>")
            .requestMatchers(GET, "/tasks").hasAuthority("<scope3>")
            .requestMatchers(GET, "/tasks/**").hasAuthority"<scope4>")
    }.oauth2ResourceServer {
        it.jwt(withDefaults())
    }

    return http.build()
}

Based on this config, all the incoming requests should be handled with an authenticated user. When I was trying to connect to wss://<host>:<port>/websocket using Postman, I was getting javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated error, because I didn't set up an authentication in Postman.

I adjusted the configuration by adding a new line into the authorizeHttpRequests section:

authorizeHttpRequests {
   it
     .requestMatchers(PUT, "/tasks/**").hasAuthority("<scope1>")
     .requestMatchers(POST, "/tasks").hasAuthority("<scope2>")
     .requestMatchers(GET, "/tasks").hasAuthority("<scope3>")
     .requestMatchers(GET, "/tasks/**").hasAuthority"<scope4>")
     .requestMatchers("/websocket").permitAll() // new setting
}

Using the new setting I can send a request to /websocket without authentication.

The second option was to set up authentication in Postman when I was trying to connect to the WebSocket using the first version of the configuration.

HereAndBeyond
  • 794
  • 1
  • 8
  • 17
-9

if you are in dev mode with not valid certificate, why not just set weClient.setUseInsecureSSL(true). works for me

Eliran Malka
  • 15,821
  • 6
  • 77
  • 100