[PM-39840] fix: Use dedicated OkHttpClient for fill-assist to prevent load-balancer prompt (#7131)

This commit is contained in:
aj-rosado
2026-07-03 12:04:33 +00:00
committed by GitHub
parent 3ece24b0fd
commit 200794cd2b
2 changed files with 50 additions and 2 deletions
@@ -67,7 +67,7 @@ internal class RetrofitsImpl(
//region Fill-Assist Retrofit
override val fillAssistRetrofit: Retrofit by lazy {
createUnauthenticatedRetrofit(
createExternalRetrofit(
baseUrlInterceptor = baseUrlInterceptors.fillAssistInterceptor,
)
}
@@ -111,6 +111,14 @@ internal class RetrofitsImpl(
.configureSsl(certificateProvider = certificateProvider)
.build()
// For requests to external (non-Bitwarden) URLs. CookieInterceptor must be excluded because
// it treats all 302s as Bitwarden load-balancer auth redirects, which is only correct for
// Bitwarden's own infrastructure.
private val externalOkHttpClient: OkHttpClient = OkHttpClient.Builder()
.addInterceptor(headersInterceptor)
.configureSsl(certificateProvider = certificateProvider)
.build()
private val authenticatedOkHttpClient: OkHttpClient by lazy {
baseOkHttpClient
.newBuilder()
@@ -162,5 +170,20 @@ internal class RetrofitsImpl(
)
.build()
private fun createExternalRetrofit(
baseUrlInterceptor: BaseUrlInterceptor,
): Retrofit =
baseRetrofit
.newBuilder()
.client(
externalOkHttpClient
.newBuilder()
.addInterceptor(baseUrlInterceptor)
.addInterceptor(loggingInterceptor)
.addInterceptor(permissionInterceptor)
.build(),
)
.build()
//endregion Helper properties and functions
}
@@ -47,6 +47,9 @@ class RetrofitsTest {
every { eventsInterceptor } returns mockk {
mockIntercept { isEventsInterceptorCalled = true }
}
every { fillAssistInterceptor } returns mockk {
mockIntercept { isFillAssistInterceptorCalled = true }
}
}
private val cookieInterceptor = mockk<CookieInterceptor> {
mockIntercept { isCookieInterceptorCalled = true }
@@ -82,6 +85,7 @@ class RetrofitsTest {
private var isHeadersInterceptorCalled = false
private var isIdentityInterceptorCalled = false
private var isEventsInterceptorCalled = false
private var isFillAssistInterceptorCalled = false
private var isRefreshAuthenticatorCalled = false
@Before
@@ -248,6 +252,27 @@ class RetrofitsTest {
assertFalse(isEventsInterceptorCalled)
}
@Test
fun `fillAssistRetrofit should invoke the correct interceptors`() = runBlocking {
val testApi = retrofits
.fillAssistRetrofit
.createMockRetrofit()
.create<TestApi>()
server.enqueue(MockResponse().setBody("""{}"""))
testApi.test()
assertFalse(isAuthInterceptorCalled)
assertFalse(isApiInterceptorCalled)
assertFalse(isCookieInterceptorCalled)
assertTrue(isPermissionInterceptorCalled)
assertTrue(isHeadersInterceptorCalled)
assertFalse(isIdentityInterceptorCalled)
assertFalse(isEventsInterceptorCalled)
assertTrue(isFillAssistInterceptorCalled)
}
@Test
fun `createStaticRetrofit when authenticated should invoke the correct interceptors`() =
runBlocking {
@@ -312,7 +337,7 @@ class RetrofitsTest {
retrofits.createStaticRetrofit()
verify(exactly = 1) {
verify(exactly = 2) {
anyConstructed<OkHttpClient.Builder>().sslSocketFactory(any(), any())
}
}