Giphy / giphy-android-sdk

Home of the GIPHY SDK Android example app, along with Android SDK documentation, issue tracking, & release notes.
https://developers.giphy.com/
Mozilla Public License 2.0
94 stars 37 forks source link

SSLPeerUnverifiedException #207

Closed KaustubhInamdar1703 closed 1 year ago

KaustubhInamdar1703 commented 1 year ago

Hi Experts, I have integrated the GIPHY Android SDK into my application and I notice something strange. Below is summary:

  1. I launch the app for the first time and navigate to the activity that is supposed to launch the giphyFragmentDialog, which happens successfully the first time - I get the grid view, the selected GIF etc.
  2. When the activity is destroyed, and I launch it the second time, the GIPHY SDK provides the "Oh No! Something went wrong" error message within the grid. Clicking the "retry" button doesn't help either. The corresponding logs when this issue occurs seems to indicate an SSL server certificate verification failure. Below is a snippet:

2023-07-18 17:36:31.541 12926-13703/? E/com.giphy.sdk.core.network.engine.c: Unable to perform network request for url=https://api.giphy.com/v1/trending/searches?api_key=ABC&random_id=e881a039c5313aa6d351e3f29b303de1 javax.net.ssl.SSLPeerUnverifiedException: Hostname api.giphy.com not verified: certificate: sha1/2mcr7SyhS3e/lvnZTZyuQZaWbQ8= DN: CN=.giphy.com subjectAltNames: [.giphy.com, giphy.com] at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:205) at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:153) at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116) at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186) at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128) at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:90) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:30) at com.giphy.sdk.core.network.engine.b.f(SourceFile:15) at com.giphy.sdk.core.network.engine.b.e(Unknown Source:0) at com.giphy.sdk.core.network.engine.a.call(Unknown Source:16)

And

2023-07-18 17:36:31.596 12926-13708/? E/com.giphy.sdk.core.network.engine.c: Unable to perform network request for url=https://api.giphy.com/v1/gifs/trending?limit=25&rating=pg-13&random_id=e881a039c5313aa6d351e3f29b303de1&offset=0&api_key=ABC&pingback_id=e881a039c5313aa6d351e3f29b303de144c94574 javax.net.ssl.SSLPeerUnverifiedException: Hostname api.giphy.com not verified: certificate: sha1/2mcr7SyhS3e/lvnZTZyuQZaWbQ8= DN: CN=.giphy.com subjectAltNames: [.giphy.com, giphy.com] at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:205) at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:153) at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116) at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186) at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128) at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131)

PLease note that I have obfuscated my actual Key with "ABC" above. I presume requests are targeted to the same API endpoints the first time around where GIFs are loaded successfully, further, it is my guess that the same certificate or at least a similar chain or trust is presented across the requests. Also, I don't believe the OkHTTP implementation within the GIPHY SDK can be customized to "trust" certain full or wildcard domains.

The use of GIPHY is for a critical production app feature and any insights would be greatly appreciated.

Thanks.

KaustubhInamdar1703 commented 1 year ago

Also, I'm using version 2.3.0 of the SDK, moving to a newer version is breaking some legacy dependencies in the application.

ALexanderLonsky commented 1 year ago

@KaustubhInamdar1703 hey, Could you please provide a test project where I can reproduce this issue?

P.S. What JDK version do you use? There is a similar issue here: https://stackoverflow.com/a/57224142

Do you use Charles Proxy with your own root certificate or something similar?

KaustubhInamdar1703 commented 1 year ago

Hi @ALexanderLonsky, My JDK Version is 11.0.12. I tried creating a one activity project to replicate this, but couldn't do so. Would more logs help in diagnosing this further? Is there a way in can configure the underlying the OKHTTP client used specifically for GIPHY?

KaustubhInamdar1703 commented 1 year ago

Digging into this a little deeper. When the activity that houses the giphyFragmentDialog is launched, a Firebase lookup is done to check if the communication peer (telephone number) has the app installed. If I remove the logic to do the lookup and launch the fragment, I get the GIPHY error straightaway. This all seems really strange to me.

ALexanderLonsky commented 1 year ago

Hi @KaustubhInamdar1703, This really seems strange to me. The interesting thing is that we don't use OkHttp for API requests; it's only used by Fresco for displaying media. Though, it seems that the message comes out of OkHttp library: link

We do have Fresco setup here to handle the configuration of okHttpClientBuilder. For more context, you can refer to this link.

Regrettably, I cannot provide more assistance without an example that allows me to reproduce this issue.

So far, we have not been able to reproduce this issue on our end, either in the Android SDK or in the React Native SDK, which uses the Android SDK under the hood.

ALexanderLonsky commented 1 year ago

Oh, it's not about OkHttp3, so the Fresco setup won't help here. We use HttpURLConnection, which uses OkHttp under the hood.

KaustubhInamdar1703 commented 1 year ago

Are there any reports that you/your team have received about conflicts with other libraries and GIPHY? For example, retrofit, websockets for Android, google analytics etc?

ALexanderLonsky commented 1 year ago

It was primarily about the Exoplayer, that's what I can recall now.

KaustubhInamdar1703 commented 1 year ago

Following is the function I call before the giphyDialogFragment is launched:

private fun disableCertificateVerification() {
    val trustAllCerts: Array<TrustManager> = arrayOf(
        object : X509TrustManager {
            override fun checkClientTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {}

            override fun checkServerTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {}

            override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> {
                return arrayOf()
            }
        }
    )

    val sslContext = SSLContext.getInstance("TLS")
    sslContext.init(null, trustAllCerts, java.security.SecureRandom())
    HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.socketFactory)
    HttpsURLConnection.setDefaultHostnameVerifier { _, _ -> true }
}

I'm going to sanitize it with the appropriate domain names. However, this seems to have resolved the issue.
ALexanderLonsky commented 1 year ago

hi @KaustubhInamdar1703, thank you for the update!