Mutualize pending auth handling

This commit is contained in:
Maxime NATUREL 2022-09-21 14:55:37 +02:00
parent 6c79aae3aa
commit 892fd4445c
6 changed files with 106 additions and 179 deletions

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* 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 im.vector.app.features.auth
import im.vector.app.core.di.ActiveSessionHolder
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.auth.UIABaseAuth
import org.matrix.android.sdk.api.auth.UserPasswordAuth
import org.matrix.android.sdk.api.util.fromBase64
import timber.log.Timber
import javax.inject.Inject
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
class PendingAuthHandler @Inject constructor(
private val matrix: Matrix,
private val activeSessionHolder: ActiveSessionHolder,
) {
var uiaContinuation: Continuation<UIABaseAuth>? = null
var pendingAuth: UIABaseAuth? = null
fun ssoAuthDone() {
Timber.d("ssoAuthDone $pendingAuth , continuation: $uiaContinuation")
pendingAuth?.let {
uiaContinuation?.resume(it)
} ?: run {
uiaContinuation?.resumeWithException(IllegalArgumentException())
}
}
fun passwordAuthDone(password: String) {
Timber.d("passwordAuthDone")
val decryptedPass = matrix.secureStorageService()
.loadSecureSecret<String>(
inputStream = password.fromBase64().inputStream(),
keyAlias = ReAuthActivity.DEFAULT_RESULT_KEYSTORE_ALIAS
)
uiaContinuation?.resume(
UserPasswordAuth(
session = pendingAuth?.session,
password = decryptedPass,
user = activeSessionHolder.getActiveSession().myUserId
)
)
}
fun reAuthCancelled() {
Timber.d("reAuthCancelled")
uiaContinuation?.resumeWithException(Exception())
uiaContinuation = null
pendingAuth = null
}
}

View file

@ -32,14 +32,13 @@ import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.WaitingViewData
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.auth.PendingAuthHandler
import im.vector.app.features.raw.wellknown.SecureBackupMethod
import im.vector.app.features.raw.wellknown.getElementWellknown
import im.vector.app.features.raw.wellknown.isSecureBackupRequired
import im.vector.app.features.raw.wellknown.secureBackupMethod
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.auth.UIABaseAuth
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.auth.UserPasswordAuth
@ -57,10 +56,8 @@ import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth
import org.matrix.android.sdk.api.util.awaitCallback
import org.matrix.android.sdk.api.util.fromBase64
import java.io.OutputStream
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
class BootstrapSharedViewModel @AssistedInject constructor(
@ -71,7 +68,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
private val rawService: RawService,
private val bootstrapTask: BootstrapCrossSigningTask,
private val migrationTask: BackupToQuadSMigrationTask,
private val matrix: Matrix,
private val pendingAuthHandler: PendingAuthHandler,
) : VectorViewModel<BootstrapViewState, BootstrapActions, BootstrapViewEvents>(initialState) {
private var doesKeyBackupExist: Boolean = false
@ -85,11 +82,6 @@ class BootstrapSharedViewModel @AssistedInject constructor(
companion object : MavericksViewModelFactory<BootstrapSharedViewModel, BootstrapViewState> by hiltMavericksViewModelFactory()
// private var _pendingSession: String? = null
var uiaContinuation: Continuation<UIABaseAuth>? = null
var pendingAuth: UIABaseAuth? = null
init {
setState {
@ -272,21 +264,10 @@ class BootstrapSharedViewModel @AssistedInject constructor(
is BootstrapActions.DoMigrateWithRecoveryKey -> {
startMigrationFlow(state.step, null, action.recoveryKey)
}
BootstrapActions.SsoAuthDone -> {
uiaContinuation?.resume(DefaultBaseAuth(session = pendingAuth?.session ?: ""))
}
is BootstrapActions.PasswordAuthDone -> {
val decryptedPass = matrix.secureStorageService()
.loadSecureSecret<String>(action.password.fromBase64().inputStream(), ReAuthActivity.DEFAULT_RESULT_KEYSTORE_ALIAS)
uiaContinuation?.resume(
UserPasswordAuth(
session = pendingAuth?.session,
password = decryptedPass,
user = session.myUserId
)
)
}
BootstrapActions.SsoAuthDone -> pendingAuthHandler.ssoAuthDone()
is BootstrapActions.PasswordAuthDone -> pendingAuthHandler.passwordAuthDone(action.password)
BootstrapActions.ReAuthCancelled -> {
pendingAuthHandler.reAuthCancelled()
setState {
copy(step = BootstrapStep.AccountReAuth(stringProvider.getString(R.string.authentication_error)))
}
@ -402,13 +383,13 @@ class BootstrapSharedViewModel @AssistedInject constructor(
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
when (flowResponse.nextUncompletedStage()) {
LoginFlowTypes.PASSWORD -> {
pendingAuth = UserPasswordAuth(
pendingAuthHandler.pendingAuth = UserPasswordAuth(
// Note that _pendingSession may or may not be null, this is OK, it will be managed by the task
session = flowResponse.session,
user = session.myUserId,
password = null
)
uiaContinuation = promise
pendingAuthHandler.uiaContinuation = promise
setState {
copy(
step = BootstrapStep.AccountReAuth()
@ -417,8 +398,8 @@ class BootstrapSharedViewModel @AssistedInject constructor(
_viewEvents.post(BootstrapViewEvents.RequestReAuth(flowResponse, errCode))
}
LoginFlowTypes.SSO -> {
pendingAuth = DefaultBaseAuth(flowResponse.session)
uiaContinuation = promise
pendingAuthHandler.pendingAuth = DefaultBaseAuth(flowResponse.session)
pendingAuthHandler.uiaContinuation = promise
setState {
copy(
step = BootstrapStep.AccountReAuth()

View file

@ -23,22 +23,15 @@ import dagger.assisted.AssistedInject
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.auth.PendingAuthHandler
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.auth.UIABaseAuth
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.auth.UserPasswordAuth
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.api.failure.isInvalidUIAAuth
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth
import org.matrix.android.sdk.api.session.uia.exceptions.UiaCancelledException
import org.matrix.android.sdk.api.util.fromBase64
import timber.log.Timber
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
data class DeactivateAccountViewState(
val dummy: Boolean = false
@ -47,7 +40,7 @@ data class DeactivateAccountViewState(
class DeactivateAccountViewModel @AssistedInject constructor(
@Assisted private val initialState: DeactivateAccountViewState,
private val session: Session,
private val matrix: Matrix,
private val pendingAuthHandler: PendingAuthHandler,
) :
VectorViewModel<DeactivateAccountViewState, DeactivateAccountAction, DeactivateAccountViewEvents>(initialState) {
@ -56,39 +49,15 @@ class DeactivateAccountViewModel @AssistedInject constructor(
override fun create(initialState: DeactivateAccountViewState): DeactivateAccountViewModel
}
var uiaContinuation: Continuation<UIABaseAuth>? = null
var pendingAuth: UIABaseAuth? = null
override fun handle(action: DeactivateAccountAction) {
when (action) {
is DeactivateAccountAction.DeactivateAccount -> handleDeactivateAccount(action)
DeactivateAccountAction.SsoAuthDone -> {
Timber.d("## UIA - FallBack success")
_viewEvents.post(DeactivateAccountViewEvents.Loading())
if (pendingAuth != null) {
uiaContinuation?.resume(pendingAuth!!)
} else {
uiaContinuation?.resumeWithException(IllegalArgumentException())
}
}
DeactivateAccountAction.SsoAuthDone -> pendingAuthHandler.ssoAuthDone()
is DeactivateAccountAction.PasswordAuthDone -> {
_viewEvents.post(DeactivateAccountViewEvents.Loading())
val decryptedPass = matrix.secureStorageService()
.loadSecureSecret<String>(action.password.fromBase64().inputStream(), ReAuthActivity.DEFAULT_RESULT_KEYSTORE_ALIAS)
uiaContinuation?.resume(
UserPasswordAuth(
session = pendingAuth?.session,
password = decryptedPass,
user = session.myUserId
)
)
}
DeactivateAccountAction.ReAuthCancelled -> {
Timber.d("## UIA - Reauth cancelled")
uiaContinuation?.resumeWithException(UiaCancelledException())
uiaContinuation = null
pendingAuth = null
pendingAuthHandler.passwordAuthDone(action.password)
}
DeactivateAccountAction.ReAuthCancelled -> pendingAuthHandler.reAuthCancelled()
}
}
@ -102,8 +71,8 @@ class DeactivateAccountViewModel @AssistedInject constructor(
object : UserInteractiveAuthInterceptor {
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
_viewEvents.post(DeactivateAccountViewEvents.RequestReAuth(flowResponse, errCode))
pendingAuth = DefaultBaseAuth(session = flowResponse.session)
uiaContinuation = promise
pendingAuthHandler.pendingAuth = DefaultBaseAuth(session = flowResponse.session)
pendingAuthHandler.uiaContinuation = promise
}
}
)

View file

@ -24,12 +24,11 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.auth.PendingAuthHandler
import im.vector.app.features.login.ReAuthHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.auth.UIABaseAuth
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.auth.UserPasswordAuth
@ -40,19 +39,17 @@ import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified
import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth
import org.matrix.android.sdk.api.util.awaitCallback
import org.matrix.android.sdk.api.util.fromBase64
import org.matrix.android.sdk.flow.flow
import timber.log.Timber
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
class CrossSigningSettingsViewModel @AssistedInject constructor(
@Assisted private val initialState: CrossSigningSettingsViewState,
private val session: Session,
private val reAuthHelper: ReAuthHelper,
private val stringProvider: StringProvider,
private val matrix: Matrix,
private val pendingAuthHandler: PendingAuthHandler,
) : VectorViewModel<CrossSigningSettingsViewState, CrossSigningSettingsAction, CrossSigningSettingsViewEvents>(initialState) {
init {
@ -77,9 +74,6 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(
}
}
var uiaContinuation: Continuation<UIABaseAuth>? = null
var pendingAuth: UIABaseAuth? = null
@AssistedFactory
interface Factory : MavericksAssistedViewModelFactory<CrossSigningSettingsViewModel, CrossSigningSettingsViewState> {
override fun create(initialState: CrossSigningSettingsViewState): CrossSigningSettingsViewModel
@ -110,8 +104,8 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(
} else {
Timber.d("## UIA : initializeCrossSigning UIA > start reauth activity")
_viewEvents.post(CrossSigningSettingsViewEvents.RequestReAuth(flowResponse, errCode))
pendingAuth = DefaultBaseAuth(session = flowResponse.session)
uiaContinuation = promise
pendingAuthHandler.pendingAuth = DefaultBaseAuth(session = flowResponse.session)
pendingAuthHandler.uiaContinuation = promise
}
}
}, it
@ -125,31 +119,11 @@ class CrossSigningSettingsViewModel @AssistedInject constructor(
}
Unit
}
is CrossSigningSettingsAction.SsoAuthDone -> {
Timber.d("## UIA - FallBack success")
if (pendingAuth != null) {
uiaContinuation?.resume(pendingAuth!!)
} else {
uiaContinuation?.resumeWithException(IllegalArgumentException())
}
}
is CrossSigningSettingsAction.PasswordAuthDone -> {
val decryptedPass = matrix.secureStorageService()
.loadSecureSecret<String>(action.password.fromBase64().inputStream(), ReAuthActivity.DEFAULT_RESULT_KEYSTORE_ALIAS)
uiaContinuation?.resume(
UserPasswordAuth(
session = pendingAuth?.session,
password = decryptedPass,
user = session.myUserId
)
)
}
is CrossSigningSettingsAction.SsoAuthDone -> pendingAuthHandler.ssoAuthDone()
is CrossSigningSettingsAction.PasswordAuthDone -> pendingAuthHandler.passwordAuthDone(action.password)
CrossSigningSettingsAction.ReAuthCancelled -> {
Timber.d("## UIA - Reauth cancelled")
_viewEvents.post(CrossSigningSettingsViewEvents.HideModalWaitingView)
uiaContinuation?.resumeWithException(Exception())
uiaContinuation = null
pendingAuth = null
pendingAuthHandler.reAuthCancelled()
}
}
}

View file

@ -32,7 +32,7 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.PublishDataSource
import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.auth.PendingAuthHandler
import im.vector.app.features.login.ReAuthHelper
import im.vector.app.features.settings.devices.v2.list.CheckIfSessionIsInactiveUseCase
import im.vector.app.features.settings.devices.v2.verification.GetEncryptionTrustLevelForDeviceUseCase
@ -45,7 +45,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.NoOpMatrixCallback
import org.matrix.android.sdk.api.auth.UIABaseAuth
@ -67,13 +66,11 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransa
import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth
import org.matrix.android.sdk.api.util.awaitCallback
import org.matrix.android.sdk.api.util.fromBase64
import org.matrix.android.sdk.flow.flow
import timber.log.Timber
import javax.net.ssl.HttpsURLConnection
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
data class DevicesViewState(
val myDeviceId: String = "",
@ -100,15 +97,12 @@ class DevicesViewModel @AssistedInject constructor(
private val session: Session,
private val reAuthHelper: ReAuthHelper,
private val stringProvider: StringProvider,
private val matrix: Matrix,
private val pendingAuthHandler: PendingAuthHandler,
private val checkIfSessionIsInactiveUseCase: CheckIfSessionIsInactiveUseCase,
getCurrentSessionCrossSigningInfoUseCase: GetCurrentSessionCrossSigningInfoUseCase,
private val getEncryptionTrustLevelForDeviceUseCase: GetEncryptionTrustLevelForDeviceUseCase,
) : VectorViewModel<DevicesViewState, DevicesAction, DevicesViewEvents>(initialState), VerificationService.Listener {
var uiaContinuation: Continuation<UIABaseAuth>? = null
var pendingAuth: UIABaseAuth? = null
@AssistedFactory
interface Factory : MavericksAssistedViewModelFactory<DevicesViewModel, DevicesViewState> {
override fun create(initialState: DevicesViewState): DevicesViewModel
@ -232,37 +226,9 @@ class DevicesViewModel @AssistedInject constructor(
is DevicesAction.CompleteSecurity -> handleCompleteSecurity()
is DevicesAction.MarkAsManuallyVerified -> handleVerifyManually(action)
is DevicesAction.VerifyMyDeviceManually -> handleShowDeviceCryptoInfo(action)
is DevicesAction.SsoAuthDone -> {
// we should use token based auth
// _viewEvents.post(CrossSigningSettingsViewEvents.ShowModalWaitingView(null))
// will release the interactive auth interceptor
Timber.d("## UIA - FallBack success $pendingAuth , continuation: $uiaContinuation")
if (pendingAuth != null) {
uiaContinuation?.resume(pendingAuth!!)
} else {
uiaContinuation?.resumeWithException(IllegalArgumentException())
}
Unit
}
is DevicesAction.PasswordAuthDone -> {
val decryptedPass = matrix.secureStorageService()
.loadSecureSecret<String>(action.password.fromBase64().inputStream(), ReAuthActivity.DEFAULT_RESULT_KEYSTORE_ALIAS)
uiaContinuation?.resume(
UserPasswordAuth(
session = pendingAuth?.session,
password = decryptedPass,
user = session.myUserId
)
)
Unit
}
DevicesAction.ReAuthCancelled -> {
Timber.d("## UIA - Reauth cancelled")
// _viewEvents.post(DevicesViewEvents.Loading)
uiaContinuation?.resumeWithException(Exception())
uiaContinuation = null
pendingAuth = null
}
is DevicesAction.SsoAuthDone -> pendingAuthHandler.ssoAuthDone()
is DevicesAction.PasswordAuthDone -> pendingAuthHandler.passwordAuthDone(action.password)
DevicesAction.ReAuthCancelled -> pendingAuthHandler.reAuthCancelled()
DevicesAction.ResetSecurity -> _viewEvents.post(DevicesViewEvents.PromptResetSecrets)
}
}
@ -371,8 +337,8 @@ class DevicesViewModel @AssistedInject constructor(
} else {
Timber.d("## UIA : deleteDevice UIA > start reauth activity")
_viewEvents.post(DevicesViewEvents.RequestReAuth(flowResponse, errCode))
pendingAuth = DefaultBaseAuth(session = flowResponse.session)
uiaContinuation = promise
pendingAuthHandler.pendingAuth = DefaultBaseAuth(session = flowResponse.session)
pendingAuthHandler.uiaContinuation = promise
}
}
}, it)

View file

@ -28,33 +28,26 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.ReadOnceTrue
import im.vector.app.features.auth.ReAuthActivity
import im.vector.app.features.auth.PendingAuthHandler
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.auth.UIABaseAuth
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.auth.UserPasswordAuth
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth
import org.matrix.android.sdk.api.util.fromBase64
import org.matrix.android.sdk.flow.flow
import timber.log.Timber
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
class ThreePidsSettingsViewModel @AssistedInject constructor(
@Assisted initialState: ThreePidsSettingsViewState,
private val session: Session,
private val stringProvider: StringProvider,
private val matrix: Matrix,
private val pendingAuthHandler: PendingAuthHandler,
) : VectorViewModel<ThreePidsSettingsViewState, ThreePidsSettingsAction, ThreePidsSettingsViewEvents>(initialState) {
// UIA session
private var pendingThreePid: ThreePid? = null
// private var pendingSession: String? = null
private suspend fun loadingSuspendable(block: suspend () -> Unit) {
runCatching { block() }
@ -126,42 +119,17 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
is ThreePidsSettingsAction.CancelThreePid -> handleCancelThreePid(action)
is ThreePidsSettingsAction.DeleteThreePid -> handleDeleteThreePid(action)
is ThreePidsSettingsAction.ChangeUiState -> handleChangeUiState(action)
ThreePidsSettingsAction.SsoAuthDone -> {
Timber.d("## UIA - FallBack success")
if (pendingAuth != null) {
uiaContinuation?.resume(pendingAuth!!)
} else {
uiaContinuation?.resumeWithException(IllegalArgumentException())
}
}
is ThreePidsSettingsAction.PasswordAuthDone -> {
val decryptedPass = matrix.secureStorageService()
.loadSecureSecret<String>(action.password.fromBase64().inputStream(), ReAuthActivity.DEFAULT_RESULT_KEYSTORE_ALIAS)
uiaContinuation?.resume(
UserPasswordAuth(
session = pendingAuth?.session,
password = decryptedPass,
user = session.myUserId
)
)
}
ThreePidsSettingsAction.ReAuthCancelled -> {
Timber.d("## UIA - Reauth cancelled")
uiaContinuation?.resumeWithException(Exception())
uiaContinuation = null
pendingAuth = null
}
ThreePidsSettingsAction.SsoAuthDone -> pendingAuthHandler.ssoAuthDone()
is ThreePidsSettingsAction.PasswordAuthDone -> pendingAuthHandler.passwordAuthDone(action.password)
ThreePidsSettingsAction.ReAuthCancelled -> pendingAuthHandler.reAuthCancelled()
}
}
var uiaContinuation: Continuation<UIABaseAuth>? = null
var pendingAuth: UIABaseAuth? = null
private val uiaInterceptor = object : UserInteractiveAuthInterceptor {
override fun performStage(flowResponse: RegistrationFlowResponse, errCode: String?, promise: Continuation<UIABaseAuth>) {
_viewEvents.post(ThreePidsSettingsViewEvents.RequestReAuth(flowResponse, errCode))
pendingAuth = DefaultBaseAuth(session = flowResponse.session)
uiaContinuation = promise
pendingAuthHandler.pendingAuth = DefaultBaseAuth(session = flowResponse.session)
pendingAuthHandler.uiaContinuation = promise
}
}