[BWA-182] Add mTLS support for Glide image loading (#6125)

Co-authored-by: David Perez <david@livefront.com>
This commit is contained in:
aj-rosado
2026-01-30 19:57:59 +00:00
committed by GitHub
parent 5531b478d3
commit 9f82b42e36
6 changed files with 178 additions and 32 deletions

View File

@@ -5,8 +5,8 @@ import com.bitwarden.network.interceptor.AuthTokenManager
import com.bitwarden.network.interceptor.BaseUrlInterceptor
import com.bitwarden.network.interceptor.BaseUrlInterceptors
import com.bitwarden.network.interceptor.HeadersInterceptor
import com.bitwarden.network.ssl.BitwardenX509ExtendedKeyManager
import com.bitwarden.network.ssl.CertificateProvider
import com.bitwarden.network.ssl.configureSsl
import com.bitwarden.network.util.HEADER_KEY_AUTHORIZATION
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
@@ -15,11 +15,6 @@ import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.kotlinx.serialization.asConverterFactory
import timber.log.Timber
import java.security.KeyStore
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
/**
* Primary implementation of [Retrofits].
@@ -97,7 +92,7 @@ internal class RetrofitsImpl(
private val baseOkHttpClient: OkHttpClient = OkHttpClient.Builder()
.addInterceptor(headersInterceptor)
.configureSsl()
.configureSsl(certificateProvider = certificateProvider)
.build()
private val authenticatedOkHttpClient: OkHttpClient by lazy {
@@ -149,28 +144,5 @@ internal class RetrofitsImpl(
)
.build()
private fun createSslTrustManagers(): Array<TrustManager> =
TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm())
.apply { init(null as KeyStore?) }
.trustManagers
private fun createSslContext(certificateProvider: CertificateProvider): SSLContext = SSLContext
.getInstance("TLS").apply {
init(
arrayOf(
BitwardenX509ExtendedKeyManager(certificateProvider = certificateProvider),
),
createSslTrustManagers(),
null,
)
}
private fun OkHttpClient.Builder.configureSsl(): OkHttpClient.Builder =
sslSocketFactory(
createSslContext(certificateProvider = certificateProvider).socketFactory,
createSslTrustManagers().first() as X509TrustManager,
)
//endregion Helper properties and functions
}

View File

@@ -0,0 +1,63 @@
package com.bitwarden.network.ssl
import okhttp3.OkHttpClient
import java.security.KeyStore
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
/**
* Creates an [OkHttpClient] configured with mTLS support using this [CertificateProvider].
*
* The returned client will present the client certificate from this provider during TLS
* handshakes, allowing requests to pass through mTLS checks.
*/
fun CertificateProvider.createMtlsOkHttpClient(): OkHttpClient =
OkHttpClient.Builder()
.configureSsl(certificateProvider = this)
.build()
/**
* Configures the [OkHttpClient.Builder] to use the a `SSLSocketFactory` as provided by the
* [CertificateProvider].
*/
fun OkHttpClient.Builder.configureSsl(
certificateProvider: CertificateProvider,
): OkHttpClient.Builder {
val trustManagers = sslTrustManagers
val sslContext = certificateProvider.createSslContext(trustManagers = trustManagers)
return sslSocketFactory(
sslContext.socketFactory,
trustManagers.first() as X509TrustManager,
)
}
/**
* Creates an [SSLContext] configured with mTLS support using this [CertificateProvider].
*
* The returned SSLContext will present the client certificate from this provider during
* TLS handshakes, enabling mutual TLS authentication.
*/
private fun CertificateProvider.createSslContext(
trustManagers: Array<TrustManager>,
): SSLContext = SSLContext.getInstance("TLS").apply {
init(
arrayOf(
BitwardenX509ExtendedKeyManager(certificateProvider = this@createSslContext),
),
trustManagers,
null,
)
}
/**
* Creates default [TrustManager]s for verifying server certificates.
*
* Uses the system's default trust anchors (trusted CA certificates).
*/
private val sslTrustManagers: Array<TrustManager>
get() = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm())
.apply { init(null as KeyStore?) }
.trustManagers