Ignore url override from credential if it is not valid (#2822)

This commit is contained in:
Benoit Marty 2021-02-17 16:35:24 +01:00 committed by Benoit Marty
parent d19cedef88
commit 0e322630f1
4 changed files with 103 additions and 10 deletions

View File

@ -14,6 +14,7 @@ Bugfix 🐛:
- VoIP : fix audio devices output - VoIP : fix audio devices output
- Fix crash after initial sync on Dendrite - Fix crash after initial sync on Dendrite
- Fix crash reported by PlayStore (#2707) - Fix crash reported by PlayStore (#2707)
- Ignore url override from credential if it is not valid (#2822)
Translations 🗣: Translations 🗣:
- -

View File

@ -20,7 +20,9 @@ import android.content.Context
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import io.realm.RealmConfiguration
import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.AuthenticationService
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import org.matrix.android.sdk.api.legacy.LegacySessionImporter import org.matrix.android.sdk.api.legacy.LegacySessionImporter
import org.matrix.android.sdk.internal.auth.db.AuthRealmMigration import org.matrix.android.sdk.internal.auth.db.AuthRealmMigration
import org.matrix.android.sdk.internal.auth.db.AuthRealmModule import org.matrix.android.sdk.internal.auth.db.AuthRealmModule
@ -32,8 +34,6 @@ import org.matrix.android.sdk.internal.database.RealmKeysUtils
import org.matrix.android.sdk.internal.di.AuthDatabase import org.matrix.android.sdk.internal.di.AuthDatabase
import org.matrix.android.sdk.internal.legacy.DefaultLegacySessionImporter import org.matrix.android.sdk.internal.legacy.DefaultLegacySessionImporter
import org.matrix.android.sdk.internal.wellknown.WellknownModule import org.matrix.android.sdk.internal.wellknown.WellknownModule
import io.realm.RealmConfiguration
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
import java.io.File import java.io.File
@Module(includes = [WellknownModule::class]) @Module(includes = [WellknownModule::class])
@ -82,6 +82,9 @@ internal abstract class AuthModule {
@Binds @Binds
abstract fun bindDirectLoginTask(task: DefaultDirectLoginTask): DirectLoginTask abstract fun bindDirectLoginTask(task: DefaultDirectLoginTask): DirectLoginTask
@Binds
abstract fun bindGetVersionTask(task: DefaultIsValidClientServerApiTask): IsValidClientServerApiTask
@Binds @Binds
abstract fun bindHomeServerHistoryService(service: DefaultHomeServerHistoryService): HomeServerHistoryService abstract fun bindHomeServerHistoryService(service: DefaultHomeServerHistoryService): HomeServerHistoryService
} }

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2021 The Matrix.org Foundation C.I.C.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.matrix.android.sdk.internal.auth
import dagger.Lazy
import okhttp3.OkHttpClient
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.internal.auth.data.LoginFlowResponse
import org.matrix.android.sdk.internal.di.Unauthenticated
import org.matrix.android.sdk.internal.network.RetrofitFactory
import org.matrix.android.sdk.internal.network.executeRequest
import org.matrix.android.sdk.internal.network.httpclient.addSocketFactory
import org.matrix.android.sdk.internal.task.Task
import javax.inject.Inject
import javax.net.ssl.HttpsURLConnection
internal interface IsValidClientServerApiTask : Task<IsValidClientServerApiTask.Params, Boolean> {
data class Params(
val homeServerConnectionConfig: HomeServerConnectionConfig
)
}
internal class DefaultIsValidClientServerApiTask @Inject constructor(
@Unauthenticated
private val okHttpClient: Lazy<OkHttpClient>,
private val retrofitFactory: RetrofitFactory
) : IsValidClientServerApiTask {
override suspend fun execute(params: IsValidClientServerApiTask.Params): Boolean {
val client = buildClient(params.homeServerConnectionConfig)
val homeServerUrl = params.homeServerConnectionConfig.homeServerUri.toString()
val authAPI = retrofitFactory.create(client, homeServerUrl)
.create(AuthAPI::class.java)
return try {
executeRequest<LoginFlowResponse>(null) {
apiCall = authAPI.getLoginFlows()
}
// We get a response, so the API is valid
true
} catch (failure: Throwable) {
if (failure is Failure.OtherServerError
&& failure.httpCode == HttpsURLConnection.HTTP_NOT_FOUND /* 404 */) {
// Probably not valid
false
} else {
// Other error
throw failure
}
}
}
private fun buildClient(homeServerConnectionConfig: HomeServerConnectionConfig): OkHttpClient {
return okHttpClient.get()
.newBuilder()
.addSocketFactory(homeServerConnectionConfig)
.build()
}
}

View File

@ -20,6 +20,7 @@ import android.net.Uri
import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.auth.data.Credentials
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
import org.matrix.android.sdk.api.auth.data.SessionParams import org.matrix.android.sdk.api.auth.data.SessionParams
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.SessionManager
import timber.log.Timber import timber.log.Timber
@ -32,7 +33,8 @@ internal interface SessionCreator {
internal class DefaultSessionCreator @Inject constructor( internal class DefaultSessionCreator @Inject constructor(
private val sessionParamsStore: SessionParamsStore, private val sessionParamsStore: SessionParamsStore,
private val sessionManager: SessionManager, private val sessionManager: SessionManager,
private val pendingSessionStore: PendingSessionStore private val pendingSessionStore: PendingSessionStore,
private val isValidClientServerApiTask: IsValidClientServerApiTask
) : SessionCreator { ) : SessionCreator {
/** /**
@ -43,16 +45,28 @@ internal class DefaultSessionCreator @Inject constructor(
// We can cleanup the pending session params // We can cleanup the pending session params
pendingSessionStore.delete() pendingSessionStore.delete()
val overriddenUrl = credentials.discoveryInformation?.homeServer?.baseURL
// remove trailing "/"
?.trim { it == '/' }
?.takeIf { it.isNotBlank() }
?.also { Timber.d("Overriding homeserver url to $it (will check if valid)") }
?.let { Uri.parse(it) }
?.takeIf {
// Validate the URL, if the configuration is wrong server side, do not override
tryOrNull {
isValidClientServerApiTask.execute(
IsValidClientServerApiTask.Params(
homeServerConnectionConfig.copy(homeServerUri = it)
)
)
.also { Timber.d("Overriding homeserver url: $it") }
} ?: true // In case of other error (no network, etc.), consider it is valid...
}
val sessionParams = SessionParams( val sessionParams = SessionParams(
credentials = credentials, credentials = credentials,
homeServerConnectionConfig = homeServerConnectionConfig.copy( homeServerConnectionConfig = homeServerConnectionConfig.copy(
homeServerUri = credentials.discoveryInformation?.homeServer?.baseURL homeServerUri = overriddenUrl ?: homeServerConnectionConfig.homeServerUri,
// remove trailing "/"
?.trim { it == '/' }
?.takeIf { it.isNotBlank() }
?.also { Timber.d("Overriding homeserver url to $it") }
?.let { Uri.parse(it) }
?: homeServerConnectionConfig.homeServerUri,
identityServerUri = credentials.discoveryInformation?.identityServer?.baseURL identityServerUri = credentials.discoveryInformation?.identityServer?.baseURL
// remove trailing "/" // remove trailing "/"
?.trim { it == '/' } ?.trim { it == '/' }