diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/device/DeviceManager.kt b/android/app/src/main/kotlin/com/yubico/authenticator/device/DeviceManager.kt index 1791b4d9..76998807 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/device/DeviceManager.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/device/DeviceManager.kt @@ -30,9 +30,7 @@ import com.yubico.yubikit.core.YubiKeyDevice import com.yubico.yubikit.core.smartcard.scp.ScpKeyParams import com.yubico.yubikit.management.Capability import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.delay import org.slf4j.LoggerFactory -import kotlin.coroutines.suspendCoroutine interface DeviceListener { // a USB device is connected diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/fido/FidoConnectionHelper.kt b/android/app/src/main/kotlin/com/yubico/authenticator/fido/FidoConnectionHelper.kt index 4d5f86aa..bb0ede5f 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/fido/FidoConnectionHelper.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/fido/FidoConnectionHelper.kt @@ -17,6 +17,7 @@ package com.yubico.authenticator.fido import com.yubico.authenticator.device.DeviceManager +import com.yubico.authenticator.device.Info import com.yubico.authenticator.fido.data.YubiKitFidoSession import com.yubico.authenticator.yubikit.DeviceInfoHelper.Companion.getDeviceInfo import com.yubico.authenticator.yubikit.withConnection @@ -24,11 +25,15 @@ import com.yubico.yubikit.android.transport.usb.UsbYubiKeyDevice import com.yubico.yubikit.core.fido.FidoConnection import com.yubico.yubikit.core.util.Result import org.slf4j.LoggerFactory +import java.util.Timer +import java.util.TimerTask import kotlin.coroutines.cancellation.CancellationException import kotlin.coroutines.suspendCoroutine +import kotlin.concurrent.schedule class FidoConnectionHelper(private val deviceManager: DeviceManager) { private var pendingAction: FidoAction? = null + private var deviceInfoTimer: TimerTask? = null fun invokePending(fidoSession: YubiKitFidoSession) { pendingAction?.let { action -> @@ -38,6 +43,7 @@ class FidoConnectionHelper(private val deviceManager: DeviceManager) { } fun cancelPending() { + deviceInfoTimer?.cancel() pendingAction?.let { action -> action.invoke(Result.failure(CancellationException())) pendingAction = null @@ -67,7 +73,7 @@ class FidoConnectionHelper(private val deviceManager: DeviceManager) { block(YubiKitFidoSession(it)) }.also { if (updateDeviceInfo) { - deviceManager.setDeviceInfo(getDeviceInfo(device)) + scheduleDeviceInfoUpdate(getDeviceInfo(device)) } } @@ -91,6 +97,14 @@ class FidoConnectionHelper(private val deviceManager: DeviceManager) { } } + fun scheduleDeviceInfoUpdate(deviceInfo: Info?) { + deviceInfoTimer?.cancel() + deviceInfoTimer = Timer("update-device-info", false).schedule(500) { + logger.debug("Updating device info") + deviceManager.setDeviceInfo(deviceInfo) + } + } + companion object { private val logger = LoggerFactory.getLogger(FidoConnectionHelper::class.java) } diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/fido/FidoManager.kt b/android/app/src/main/kotlin/com/yubico/authenticator/fido/FidoManager.kt index 56659c37..f9381c84 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/fido/FidoManager.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/fido/FidoManager.kt @@ -199,7 +199,7 @@ class FidoManager( } if (updateDeviceInfo.getAndSet(false)) { - deviceManager.setDeviceInfo(getDeviceInfo(device)) + connectionHelper.scheduleDeviceInfoUpdate(getDeviceInfo(device)) } } catch (e: Exception) { // something went wrong, try to get DeviceInfo from any available connection type diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/oath/OathManager.kt b/android/app/src/main/kotlin/com/yubico/authenticator/oath/OathManager.kt index 895fa1bd..c453c489 100644 --- a/android/app/src/main/kotlin/com/yubico/authenticator/oath/OathManager.kt +++ b/android/app/src/main/kotlin/com/yubico/authenticator/oath/OathManager.kt @@ -26,6 +26,7 @@ import com.yubico.authenticator.* import com.yubico.authenticator.device.Capabilities import com.yubico.authenticator.device.DeviceListener import com.yubico.authenticator.device.DeviceManager +import com.yubico.authenticator.device.Info import com.yubico.authenticator.device.UnknownDevice import com.yubico.authenticator.oath.data.Code import com.yubico.authenticator.oath.data.CodeType @@ -63,10 +64,12 @@ import kotlinx.serialization.encodeToString import org.slf4j.LoggerFactory import java.io.IOException import java.net.URI +import java.util.Timer +import java.util.TimerTask import java.util.concurrent.Executors import java.util.concurrent.atomic.AtomicBoolean import kotlin.coroutines.suspendCoroutine -import kotlin.random.Random +import kotlin.concurrent.schedule typealias OathAction = (Result) -> Unit @@ -108,8 +111,10 @@ class OathManager( private var refreshJob: Job? = null private var addToAny = false private val updateDeviceInfo = AtomicBoolean(false) + private var deviceInfoTimer: TimerTask? = null override fun onPause() { + deviceInfoTimer?.cancel() // cancel any pending actions, except for addToAny if (!addToAny) { pendingAction?.let { @@ -294,7 +299,7 @@ class OathManager( ) if (updateDeviceInfo.getAndSet(false)) { - deviceManager.setDeviceInfo(getDeviceInfo(device)) + scheduleDeviceInfoUpdate(getDeviceInfo(device)) } } catch (e: Exception) { // OATH not enabled/supported, try to get DeviceInfo over other USB interfaces @@ -675,6 +680,14 @@ class OathManager( return credential.data } + fun scheduleDeviceInfoUpdate(deviceInfo: Info?) { + deviceInfoTimer?.cancel() + deviceInfoTimer = Timer("update-device-info", false).schedule(500) { + logger.debug("Updating device info") + deviceManager.setDeviceInfo(deviceInfo) + } + } + private suspend fun useOathSession( unlock: Boolean = true, updateDeviceInfo: Boolean = false, @@ -702,7 +715,7 @@ class OathManager( block(getOathSession(it)) }.also { if (updateDeviceInfo) { - deviceManager.setDeviceInfo(getDeviceInfo(device)) + scheduleDeviceInfoUpdate(getDeviceInfo(device)) } } diff --git a/lib/android/fido/state.dart b/lib/android/fido/state.dart index 9398c20e..b2850c23 100644 --- a/lib/android/fido/state.dart +++ b/lib/android/fido/state.dart @@ -393,8 +393,7 @@ class _FidoMethodChannelNotifier extends MethodChannelNotifier { Future reset() async => invoke('reset', { 'operationSuccess': l10n.s_nfc_fido_reset_success, - 'operationFailure': l10n.s_nfc_fido_reset_failure, - 'showSuccess': true + 'operationFailure': l10n.s_nfc_fido_reset_failure }); Future setPin(String newPin, {String? oldPin}) async => @@ -405,8 +404,7 @@ class _FidoMethodChannelNotifier extends MethodChannelNotifier { : l10n.s_pin_set, 'operationFailure': oldPin != null ? l10n.s_nfc_fido_change_pin_failure - : l10n.s_nfc_fido_set_pin_failure, - 'showSuccess': true + : l10n.s_nfc_fido_set_pin_failure }); Future unlock(String pin) async => invoke('unlock', {