Keselme
Keselme

Reputation: 4279

SSLHandshakeException - Chain chain validation failed, how to solve?

in my application I am trying to do a HTTPS POST request to my server. However, I keep getting SSLHandshakeException - Chain chain validation failed, all the time. I tried to send a request using POSTMAN and I got a response from the server. What can be causing this error when I try to send the request from the application?

Here a code snippet where I try to send the post request:

   public static JSONObject getDataLibConfiguration(Context context) throws HttpRequestException {

    int statusCode = 0;

    JSONObject commonInformation;
    HttpsURLConnection connection = null;

    try {

        commonInformation = ConfigurationProcessor.getCommonInformation(context);
        if (commonInformation == null) {
            return null;
        }

        URL url = new URL(BuildConfig.SERVER_CONFIG_URL);
        if (BuildConfig.DEBUG) {
            LogUtils.d(TAG, "url = " + url.getPath());
        }

        connection = getHttpsConnection(url);
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        connection.setRequestProperty("Content-Encoding", "gzip");

        byte[] gzipped = HttpUtils.gzip(commonInformation.toString());
        cos = new CountingOutputStream(connection.getOutputStream()); //<-- This is where I get the exception
        cos.write(gzipped);
        cos.flush();

        statusCode = connection.getResponseCode();
        // More code her
 }

private static HttpsURLConnection getHttpsConnection(URL url) throws IOException, GeneralSecurityException {

        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            MatchDomainTrustManager myTrustManager = new MatchDomainTrustManager(url.getHost());
            TrustManager[] tms = new TrustManager[]{myTrustManager};
            sslContext.init(null, tms, null);
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
            connection.setSSLSocketFactory(sslSocketFactory);
        } catch (AssertionError ex) {
            if (BuildConfig.DEBUG) {
                LogFileUtils.e(TAG, "Exception in getHttpsConnection: " + ex.getMessage());
            }
            LogUtils.e(TAG, "Exception: " + ex.toString());
        }
        return connection;
    }

Upvotes: 96

Views: 95835

Answers (14)

Sagan
Sagan

Reputation: 110

In my case I had to add trusted certificate. I got the certificate from Chrome by visiting my website and clicking the options on the left to the url field and navigating through security to view that certificate and in the preview on the second tab called details you click export button on the bottom and I chose base64 encoded ASCII *.crt file. Added the file into resources/raw folder.

I updated the manifest.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        ...
        android:networkSecurityConfig="@xml/network_security_config" >
            ...
    </application>
</manifest>

and then defined the network_security_config.xml file in resources/xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">your_domain.com</domain>
        <trust-anchors>
            <certificates src="@raw/your_domain_cert"/>
        </trust-anchors>
    </domain-config>
</network-security-config>

and it immeditately worked.

Upvotes: 0

Rumit Patel
Rumit Patel

Reputation: 12609

In my case SSL was not implemented and s was added by mistake after http in the URL.

Remove s from the URL and it worked.

https://example.com updated to http://example.com

Upvotes: 0

android enthusiast
android enthusiast

Reputation: 2092

In my case the date/ time was ok and I was still getting the exception. I restarted my device and the problem went away. Hope it helps someone if all the above fails.

Upvotes: 2

Vadim
Vadim

Reputation: 4463

In my case it was wrong date on the phone.

Fixing the date resolved an issue

Upvotes: 267

If you use android emulator, you can wipe data and run again, it works

Upvotes: 2

Hayk Mkrtchyan
Hayk Mkrtchyan

Reputation: 3265

In my case, the issue was with the phone date. So please check it, set to automatic.

Upvotes: 15

Md Imran Choudhury
Md Imran Choudhury

Reputation: 10057

In my case, I fetch this issue on Android Emulator. When I clear emulator cache has resolved the issue.

enter image description here

Upvotes: 35

Sachidanand Pandit
Sachidanand Pandit

Reputation: 338

I fixed this error by resetting my emulator date and time. My server is working fine just I changed the date and time of my emulator as current server time zone.

Upvotes: 6

Emir Vildanov
Emir Vildanov

Reputation: 81

@Yash Bhardwaj in the comment on @Vadim answer said that the problem was in Glide framework. I faced the same problem: Https requests to server using Ktor framework were all successful, but when Glide tried to load image from the same server, it faced the SSLHandshakeException. To solve this issue you should look here: Solve Glide SSLHandshakeException.

To make a deal with @GlideModule annotation you should import kapt plugin and add these dependencies into your app build.gradle:

implementation 'com.github.bumptech.glide:okhttp3-integration:4.11.0'
kapt 'com.github.bumptech.glide:compiler:4.12.0'

Upvotes: 1

zetatlas
zetatlas

Reputation: 700

My date and time were correct, but I didn't have "Use Network Provided Time checked" in my system settings.

I fixed this issue by going to Settings > Date and Time > Check "Use network-provided time" and also check "Use network-provided time zone".

Then this error went away.

Upvotes: 15

Sebastian M&#252;ller
Sebastian M&#252;ller

Reputation: 601

If you're using an emulated device it may solve the problem if you just 'Cold Boot' it.

Sometimes the date on those things can get stuck if you let them run for some time, which results in this expired-certificate-problem.

Upvotes: 60

harishanth raveendren
harishanth raveendren

Reputation: 614

If anyone come across this issue pertaining to specific device, then the reason should be because of incorrect date set in the device.

Upvotes: 8

Pavlo Synytsia
Pavlo Synytsia

Reputation: 101

public static void trustEveryone() {
        try {
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }});
            SSLContext context = SSLContext.getInstance("TLS");
            context.init(null, new X509TrustManager[]{new X509TrustManager(){
                public void checkClientTrusted(X509Certificate[] chain,
                                               String authType) throws CertificateException {}
                public void checkServerTrusted(X509Certificate[] chain,
                                               String authType) throws CertificateException {}
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }}}, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(
                    context.getSocketFactory());
        } catch (Exception e) { // should never happen
            e.printStackTrace();
        }
    }

or check system date of your device - I had this Exception when I tried to connect with wrong date!..

Upvotes: 10

Keselme
Keselme

Reputation: 4279

The problem was that the certificate was expired.

Upvotes: 37

Related Questions