diff --git a/CHANGES.md b/CHANGES.md index 14bde7c5d6..091b49791d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,7 @@ Bugfix 🐛: - VoIP : fix audio devices output - Fix crash after initial sync on Dendrite - Fix crash reported by PlayStore (#2707) + - Ignore url override from credential if it is not valid (#2822) Translations 🗣: - diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthModule.kt index 2ec8900f7c..451fc93fc8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthModule.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/AuthModule.kt @@ -20,7 +20,9 @@ import android.content.Context import dagger.Binds import dagger.Module import dagger.Provides +import io.realm.RealmConfiguration 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.internal.auth.db.AuthRealmMigration 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.legacy.DefaultLegacySessionImporter import org.matrix.android.sdk.internal.wellknown.WellknownModule -import io.realm.RealmConfiguration -import org.matrix.android.sdk.api.auth.HomeServerHistoryService import java.io.File @Module(includes = [WellknownModule::class]) @@ -82,6 +82,9 @@ internal abstract class AuthModule { @Binds abstract fun bindDirectLoginTask(task: DefaultDirectLoginTask): DirectLoginTask + @Binds + abstract fun bindGetVersionTask(task: DefaultIsValidClientServerApiTask): IsValidClientServerApiTask + @Binds abstract fun bindHomeServerHistoryService(service: DefaultHomeServerHistoryService): HomeServerHistoryService } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/IsValidClientServerApiTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/IsValidClientServerApiTask.kt new file mode 100644 index 0000000000..b8416d69bf --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/IsValidClientServerApiTask.kt @@ -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 { + data class Params( + val homeServerConnectionConfig: HomeServerConnectionConfig + ) +} + +internal class DefaultIsValidClientServerApiTask @Inject constructor( + @Unauthenticated + private val okHttpClient: Lazy, + 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(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() + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt index 6743e7336e..7c4a0c38ec 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/SessionCreator.kt @@ -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.HomeServerConnectionConfig 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.internal.SessionManager import timber.log.Timber @@ -32,7 +33,8 @@ internal interface SessionCreator { internal class DefaultSessionCreator @Inject constructor( private val sessionParamsStore: SessionParamsStore, private val sessionManager: SessionManager, - private val pendingSessionStore: PendingSessionStore + private val pendingSessionStore: PendingSessionStore, + private val isValidClientServerApiTask: IsValidClientServerApiTask ) : SessionCreator { /** @@ -43,16 +45,28 @@ internal class DefaultSessionCreator @Inject constructor( // We can cleanup the pending session params 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( credentials = credentials, homeServerConnectionConfig = homeServerConnectionConfig.copy( - homeServerUri = credentials.discoveryInformation?.homeServer?.baseURL - // remove trailing "/" - ?.trim { it == '/' } - ?.takeIf { it.isNotBlank() } - ?.also { Timber.d("Overriding homeserver url to $it") } - ?.let { Uri.parse(it) } - ?: homeServerConnectionConfig.homeServerUri, + homeServerUri = overriddenUrl ?: homeServerConnectionConfig.homeServerUri, identityServerUri = credentials.discoveryInformation?.identityServer?.baseURL // remove trailing "/" ?.trim { it == '/' }