Hi! I created this Http client engine for mTLS aut...
# ktor
c
Hi! I created this Http client engine for mTLS authentication
Copy code
HttpClient(OkHttp) {
    engine {
        config {
            sslSocketFactory(sslSocketFactory, trustManager)
        }
    }
    install(HttpCache)
}
but I'm getting this error when doing a request
Copy code
java.io.IOException: Required SETTINGS preface not received
                                           	at okhttp3.internal.http2.Http2Reader.readConnectionPreface(Http2Reader.kt:74)
                                           	at okhttp3.internal.http2.Http2Connection$ReaderRunnable.invoke(Http2Connection.kt:617)
                                           	at okhttp3.internal.http2.Http2Connection$ReaderRunnable.invoke(Http2Connection.kt:609)
                                           	at okhttp3.internal.concurrent.TaskQueue$execute$1.runOnce(TaskQueue.kt:98)
                                           	at okhttp3.internal.concurrent.TaskRunner.runTask(TaskRunner.kt:116)
                                           	at okhttp3.internal.concurrent.TaskRunner.access$runTask(TaskRunner.kt:42)
                                           	at okhttp3.internal.concurrent.TaskRunner$runnable$1.run(TaskRunner.kt:65)
                                           	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
                                           	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
                                           	at java.lang.Thread.run(Thread.java:1012)
Did somebody encounter something like this? Can it be because of wrong SSLContext or TrustManager configuration or it can be backend error?
a
This might be a backend problem. Can you please try to use the HTTP/1.1 protocol instead of HTTP/2?
c
@Aleksei Tirman [JB] with that I'm getting
Copy code
java.io.IOException: unexpected end of stream on <my url>...
                                           	at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.kt:210)
                                           	at okhttp3.internal.connection.Exchange.readResponseHeaders(Exchange.kt:110)
                                           	at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.kt:93)
                                           	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
                                           	at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:34)
                                           	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
                                           	at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
                                           	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
                                           	at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
                                           	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
                                           	at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
                                           	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
                                           	at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
                                           	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
                                           	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
                                           	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
                                           	at java.lang.Thread.run(Thread.java:1012)
For context: we need to use AndroidKeyStore to configure our HTTP engine with a pre installed certificate and we are getting this error. The certificate looks ok, but we don't know what causing this error
a
I suggest directly configuring the OkHttp client with mTLS to see if the problem is on the Ktor's side.
c
Its the same. So it is not on ktor side.
m
The HTTP/2 protocol, which is what the error message points to, requires TLS (HTTPS). The "SETTINGS preface" is part of the HTTP/2 handshake that occurs after the TLS handshake is complete. If the TLS handshake fails or is incomplete, the HTTP/2 connection can't even begin, and you'll see this error. Since you're implementing mTLS, the TLS handshake is the area you need to focus on.
PLEASE NOTE THE BELOW ARE COPY PASTED FROM MY NOTES, so, please excuse the language used
You can try verifying the
sslSocketFactory
and
trustManager
Correct Key and Trust Stores: Double-check that you're loading the correct client certificate and private key into your
sslSocketFactory
. Also, ensure that the
trustManager
is configured to trust the server's certificate. Common mistakes include: ◦ Using the wrong keystore or truststore files. ◦ Incorrect passwords for the keystore or key. ◦ Not including the necessary intermediate certificates in the truststore. • Self-Signed Certificates: If you're using self-signed certificates, make absolutely certain the server's certificate (or the CA that signed it) is in your client's truststore. • Certificate Chain: The client needs the full certificate chain to establish trust. If the server presents a certificate signed by an intermediate CA, the client needs to have that intermediate CA's certificate in its truststore, in addition to the root CA. • TrustManager Implementation: If you're using a custom
TrustManager
, make sure it's correctly validating the server's certificate. A common mistake is to bypass certificate validation, which can lead to security vulnerabilities and also cause issues with HTTP/2. If the above didn't work, test with a known good configuration (aka, test with a know domain) • Temporarily try connecting to a known HTTPS endpoint (e.g.,
<https://www.google.com>
) using your mTLS client to see if the basic TLS setup works. If this fails with the same error, you know the problem is definitely in your client configuration. Hope my notes are helpful in debugging this
c
Thanks for the help, and sorry for the late response. I managed to solve it. There was a problem with my sslContext. I had to initialize a KeyManagerFactory and create with it the sslContext and sslSocketFactory.