8

I am trying to make Android app, where I can get and parse HTML (from site which doesnt have API). I am using OkHttp. The site has untrusted (but valid) certificate. I am getting:

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

I've already set up the official way (https://developer.android.com/training/articles/security-ssl#java) and now I need to link it with OkHttpClient.

I tried

    OkHttpClient client = new OkHttpClient;

    OkHttpClient.Builder builder = client.newBuilder();
    builder.sslSocketFactory(sslcontext.getSocketFactory()).build();

But it doesnt work, and also it is deprecated. Thanks

Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69
Makalone LOgman
  • 948
  • 1
  • 12
  • 25

3 Answers3

16

See this documented example for adding a known trusted certificate

https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CustomTrust.java

  public CustomTrust() {
    X509TrustManager trustManager;
    SSLSocketFactory sslSocketFactory;
    try {
      trustManager = trustManagerForCertificates(trustedCertificatesInputStream());
      SSLContext sslContext = SSLContext.getInstance("TLS");
      sslContext.init(null, new TrustManager[] { trustManager }, null);
      sslSocketFactory = sslContext.getSocketFactory();
    } catch (GeneralSecurityException e) {
      throw new RuntimeException(e);
    }

    client = new OkHttpClient.Builder()
        .sslSocketFactory(sslSocketFactory, trustManager)
        .build();
  }
Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69
2

OkHttp 4.7.1 supports specific insecure hosts for development only

https://square.github.io/okhttp/changelog/

https://github.com/square/okhttp/blob/482f88300f78c3419b04379fc26c3683c10d6a9d/samples/guide/src/main/java/okhttp3/recipes/kt/DevServer.kt

  val clientCertificates = HandshakeCertificates.Builder()
      .addPlatformTrustedCertificates()
      .addInsecureHost(server.hostName)
      .build()

  val client = OkHttpClient.Builder()
      .sslSocketFactory(clientCertificates.sslSocketFactory(), clientCertificates.trustManager)
      .build()
Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69
-2

Only use for debugging. Using this code means trusting any certificate which is as good as not using https at all.


You need to use sslSocketFactory(SSLSocketFactory sslSocketFactory, X509TrustManager trustManager) which is not deprecated.

Use this variable (which creates a trust manager that does not validate certificate chains):

TrustManager[] trustAllCerts = new TrustManager[] {
    new X509TrustManager() {
        @Override
        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[]{};
        }
    }
};

and pass to sslSocketFactory() in this way:

builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);

also apply this to verify every host:

builder.hostnameVerifier(new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
});
Michał Klimczak
  • 12,674
  • 8
  • 66
  • 99
Luca Nicoletti
  • 2,265
  • 2
  • 18
  • 32
  • 13
    This is bad _standard_ advice. The original report says that it has "untrusted (but valid) certificate" so the solution should be to add that certificate or a signing CA certificate in the chain to the truststore. And the question title is "OkHTTP Client add custom certificate" – Yuri Schimke Nov 14 '18 at 19:17
  • 1
    @YuriSchimke I usually have a check for production/pre-production/development. I use this parts of code only for debugging purpose, of course not in production. – Luca Nicoletti Nov 15 '18 at 08:16