Adding a custom certificate to an OkHttp Client

11,665

Solution 1

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;
    }
});

Solution 2

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();
  }

Solution 3

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()
Share:
11,665
Makalone LOgman
Author by

Makalone LOgman

Updated on June 09, 2022

Comments

  • Makalone LOgman
    Makalone LOgman almost 2 years

    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
    Yuri Schimke over 5 years
    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"
  • Luca Nicoletti
    Luca Nicoletti over 5 years
    @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.