diff --git a/android/app/build.gradle b/android/app/build.gradle
index 92159109..d1d735d0 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -105,6 +105,8 @@ dependencies {
implementation 'com.google.android.material:material:1.9.0'
+ implementation 'com.github.tony19:logback-android:3.0.0'
+
// testing dependencies
testImplementation "junit:junit:$project.junitVersion"
testImplementation "org.mockito:mockito-core:$project.mockitoVersion"
diff --git a/android/app/src/main/assets/logback.xml b/android/app/src/main/assets/logback.xml
new file mode 100644
index 00000000..2d8d6982
--- /dev/null
+++ b/android/app/src/main/assets/logback.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ %msg
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/AppContext.kt b/android/app/src/main/kotlin/com/yubico/authenticator/AppContext.kt
index 71a9a413..2106df02 100644
--- a/android/app/src/main/kotlin/com/yubico/authenticator/AppContext.kt
+++ b/android/app/src/main/kotlin/com/yubico/authenticator/AppContext.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 Yubico.
+ * Copyright (C) 2022-2023 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,14 +16,18 @@
package com.yubico.authenticator
-import com.yubico.authenticator.logging.Log
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
+
import kotlinx.coroutines.CoroutineScope
+import org.slf4j.LoggerFactory
+
class AppContext(messenger: BinaryMessenger, coroutineScope: CoroutineScope, private val appViewModel: MainViewModel) {
private val channel = MethodChannel(messenger, "android.state.appContext")
+ private val logger = LoggerFactory.getLogger(AppContext::class.java)
+
init {
channel.setHandler(coroutineScope) { method, args ->
when (method) {
@@ -36,11 +40,7 @@ class AppContext(messenger: BinaryMessenger, coroutineScope: CoroutineScope, pri
private suspend fun setContext(subPageIndex: Int): String {
val appContext = OperationContext.getByValue(subPageIndex)
appViewModel.setAppContext(appContext)
- Log.d(TAG, "App context is now $appContext")
+ logger.debug("App context is now {}", appContext)
return NULL
}
-
- companion object {
- const val TAG = "appContext"
- }
}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/AppPreferences.kt b/android/app/src/main/kotlin/com/yubico/authenticator/AppPreferences.kt
index e5afc9c7..fd063b14 100755
--- a/android/app/src/main/kotlin/com/yubico/authenticator/AppPreferences.kt
+++ b/android/app/src/main/kotlin/com/yubico/authenticator/AppPreferences.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 Yubico.
+ * Copyright (C) 2022-2023 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,8 @@ package com.yubico.authenticator
import android.content.Context
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
-import com.yubico.authenticator.logging.Log
+
+import org.slf4j.LoggerFactory
class AppPreferences(context: Context) {
companion object {
@@ -32,15 +33,15 @@ class AppPreferences(context: Context) {
const val PREF_CLIP_KBD_LAYOUT = "flutter.prefClipKbdLayout"
const val DEFAULT_CLIP_KBD_LAYOUT = "US"
-
- const val TAG = "AppPreferences"
}
+ private val logger = LoggerFactory.getLogger(AppPreferences::class.java)
+
private val prefs: SharedPreferences =
context.getSharedPreferences(PREFS_FILE, Context.MODE_PRIVATE).also {
- Log.d(TAG, "Current app preferences:")
+ logger.debug("Current app preferences:")
it.all.map { preference ->
- Log.d(TAG, "${preference.key}: ${preference.value}")
+ logger.debug("{}: {}", preference.key, preference.value)
}
}
@@ -66,12 +67,12 @@ class AppPreferences(context: Context) {
get() = prefs.getBoolean(PREF_USB_OPEN_APP, false)
fun registerListener(listener: OnSharedPreferenceChangeListener) {
- Log.d(TAG, "registering change listener")
+ logger.debug("registering change listener")
prefs.registerOnSharedPreferenceChangeListener(listener)
}
fun unregisterListener(listener: OnSharedPreferenceChangeListener) {
prefs.unregisterOnSharedPreferenceChangeListener(listener)
- Log.d(TAG, "unregistered change listener")
+ logger.debug("unregistered change listener")
}
}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/ClipboardUtil.kt b/android/app/src/main/kotlin/com/yubico/authenticator/ClipboardUtil.kt
index 1121b0f5..3feff47e 100644
--- a/android/app/src/main/kotlin/com/yubico/authenticator/ClipboardUtil.kt
+++ b/android/app/src/main/kotlin/com/yubico/authenticator/ClipboardUtil.kt
@@ -23,11 +23,12 @@ import android.content.ClipboardManager
import android.content.Context
import android.os.Build
import android.os.PersistableBundle
-import com.yubico.authenticator.logging.Log
+
+import org.slf4j.LoggerFactory
object ClipboardUtil {
- private const val TAG = "ClipboardUtil"
+ private val logger = LoggerFactory.getLogger(ClipboardUtil::class.java)
fun setPrimaryClip(context: Context, toClipboard: String, isSensitive: Boolean) {
try {
@@ -41,7 +42,7 @@ object ClipboardUtil {
clipboardManager.setPrimaryClip(clipData)
} catch (e: Exception) {
- Log.e(TAG, "Failed to set string to clipboard", e.stackTraceToString())
+ logger.error( "Failed to set string to clipboard", e)
throw UnsupportedOperationException()
}
}
diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/DialogManager.kt b/android/app/src/main/kotlin/com/yubico/authenticator/DialogManager.kt
index 0e001c5b..49e8214f 100644
--- a/android/app/src/main/kotlin/com/yubico/authenticator/DialogManager.kt
+++ b/android/app/src/main/kotlin/com/yubico/authenticator/DialogManager.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 Yubico.
+ * Copyright (C) 2022-2023 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,8 +91,4 @@ class DialogManager(messenger: BinaryMessenger, private val coroutineScope: Coro
}
return NULL
}
-
- companion object {
- const val TAG = "dialogManager"
- }
}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt b/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt
index 78a7d6c4..173eb214 100644
--- a/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt
@@ -39,7 +39,6 @@ import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope
import com.yubico.authenticator.logging.FlutterLog
-import com.yubico.authenticator.logging.Log
import com.yubico.authenticator.oath.AppLinkMethodChannel
import com.yubico.authenticator.oath.OathManager
import com.yubico.authenticator.oath.OathViewModel
@@ -48,7 +47,6 @@ import com.yubico.yubikit.android.transport.nfc.NfcConfiguration
import com.yubico.yubikit.android.transport.nfc.NfcNotAvailable
import com.yubico.yubikit.android.transport.nfc.NfcYubiKeyDevice
import com.yubico.yubikit.android.transport.usb.UsbConfiguration
-import com.yubico.yubikit.core.Logger
import com.yubico.yubikit.core.YubiKeyDevice
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
@@ -56,6 +54,7 @@ import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.launch
import org.json.JSONObject
+import org.slf4j.LoggerFactory
import java.io.Closeable
import java.util.concurrent.Executors
@@ -73,6 +72,8 @@ class MainActivity : FlutterFragmentActivity() {
private val qrScannerCameraClosedBR = QRScannerCameraClosedBR()
private val nfcAdapterStateChangeBR = NfcAdapterStateChangedBR()
+ private val logger = LoggerFactory.getLogger(MainActivity::class.java)
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -85,8 +86,6 @@ class MainActivity : FlutterFragmentActivity() {
allowScreenshots(false)
yubikit = YubiKitManager(this)
-
- setupYubiKitLogger()
}
/**
@@ -117,7 +116,7 @@ class MainActivity : FlutterFragmentActivity() {
private fun startNfcDiscovery() =
try {
- Log.d(TAG, "Starting nfc discovery")
+ logger.debug("Starting nfc discovery")
yubikit.startNfcDiscovery(
nfcConfiguration.disableNfcDiscoverySound(appPreferences.silenceNfcSounds),
this,
@@ -131,16 +130,16 @@ class MainActivity : FlutterFragmentActivity() {
private fun stopNfcDiscovery() {
if (hasNfc) {
yubikit.stopNfcDiscovery(this)
- Log.d(TAG, "Stopped nfc discovery")
+ logger.debug("Stopped nfc discovery")
}
}
private fun startUsbDiscovery() {
- Log.d(TAG, "Starting usb discovery")
+ logger.debug("Starting usb discovery")
val usbConfiguration = UsbConfiguration().handlePermissions(true)
yubikit.startUsbDiscovery(usbConfiguration) { device ->
viewModel.setConnectedYubiKey(device) {
- Log.d(TAG, "YubiKey was disconnected, stopping usb discovery")
+ logger.debug("YubiKey was disconnected, stopping usb discovery")
stopUsbDiscovery()
}
processYubiKey(device)
@@ -149,22 +148,7 @@ class MainActivity : FlutterFragmentActivity() {
private fun stopUsbDiscovery() {
yubikit.stopUsbDiscovery()
- Log.d(TAG, "Stopped usb discovery")
- }
-
- private fun setupYubiKitLogger() {
- Logger.setLogger(object : Logger() {
- private val TAG = "yubikit"
-
- override fun logDebug(message: String) {
- // redirect yubikit debug logs to traffic
- Log.t(TAG, message)
- }
-
- override fun logError(message: String, throwable: Throwable) {
- Log.e(TAG, message, throwable.message ?: throwable.toString())
- }
- })
+ logger.debug("Stopped usb discovery")
}
@SuppressLint("WrongConstant")
@@ -230,7 +214,7 @@ class MainActivity : FlutterFragmentActivity() {
startNfcDiscovery()
}
} catch (e: Throwable) {
- Log.e(TAG, "Error processing YubiKey in AppContextManager", e.toString())
+ logger.error("Error processing YubiKey in AppContextManager", e)
}
}
} else {
@@ -280,7 +264,7 @@ class MainActivity : FlutterFragmentActivity() {
try {
it.processYubiKey(device)
} catch (e: Throwable) {
- Log.e(TAG, "Error processing YubiKey in AppContextManager", e.toString())
+ logger.error("Error processing YubiKey in AppContextManager", e)
}
}
}
@@ -336,7 +320,6 @@ class MainActivity : FlutterFragmentActivity() {
}
companion object {
- const val TAG = "MainActivity"
const val YUBICO_VENDOR_ID = 4176
const val FLAG_SECURE = WindowManager.LayoutParams.FLAG_SECURE
}
@@ -363,6 +346,9 @@ class MainActivity : FlutterFragmentActivity() {
}
class NfcAdapterStateChangedBR : BroadcastReceiver() {
+
+ private val logger = LoggerFactory.getLogger(NfcAdapterStateChangedBR::class.java)
+
companion object {
val intentFilter = IntentFilter("android.nfc.action.ADAPTER_STATE_CHANGED")
}
@@ -370,7 +356,7 @@ class MainActivity : FlutterFragmentActivity() {
override fun onReceive(context: Context?, intent: Intent?) {
intent?.let {
val state = it.getIntExtra("android.nfc.extra.ADAPTER_STATE", 0)
- Log.d(TAG, "NfcAdapter state changed to $state")
+ logger.debug("NfcAdapter state changed to {}", state)
if (state == STATE_ON || state == STATE_TURNING_OFF) {
(context as? MainActivity)?.appMethodChannel?.nfcAdapterStateChanged(state == STATE_ON)
}
@@ -430,7 +416,7 @@ class MainActivity : FlutterFragmentActivity() {
startActivity(Intent(ACTION_NFC_SETTINGS))
result.success(true)
}
- else -> Log.w(TAG, "Unknown app method: ${methodCall.method}")
+ else -> logger.warn("Unknown app method: {}", methodCall.method)
}
}
}
@@ -446,10 +432,10 @@ class MainActivity : FlutterFragmentActivity() {
private fun allowScreenshots(value: Boolean): Boolean {
// Note that FLAG_SECURE is the inverse of allowScreenshots
if (value) {
- Log.d(TAG, "Clearing FLAG_SECURE (allow screenshots)")
+ logger.debug("Clearing FLAG_SECURE (allow screenshots)")
window.clearFlags(FLAG_SECURE)
} else {
- Log.d(TAG, "Setting FLAG_SECURE (disallow screenshots)")
+ logger.debug("Setting FLAG_SECURE (disallow screenshots)")
window.setFlags(FLAG_SECURE, FLAG_SECURE)
}
diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/NdefActivity.kt b/android/app/src/main/kotlin/com/yubico/authenticator/NdefActivity.kt
index 47c5ece5..662150f6 100644
--- a/android/app/src/main/kotlin/com/yubico/authenticator/NdefActivity.kt
+++ b/android/app/src/main/kotlin/com/yubico/authenticator/NdefActivity.kt
@@ -24,9 +24,12 @@ import android.nfc.Tag
import android.os.Build
import android.os.Bundle
import android.widget.Toast
-import com.yubico.authenticator.logging.Log
+
import com.yubico.authenticator.ndef.KeyboardLayout
import com.yubico.yubikit.core.util.NdefUtils
+
+import org.slf4j.LoggerFactory
+
import java.nio.charset.StandardCharsets
typealias ResourceId = Int
@@ -34,6 +37,8 @@ typealias ResourceId = Int
class NdefActivity : Activity() {
private lateinit var appPreferences: AppPreferences
+ private val logger = LoggerFactory.getLogger(NdefActivity::class.java)
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
appPreferences = AppPreferences(this)
@@ -68,10 +73,9 @@ class NdefActivity : Activity() {
}
} catch (illegalArgumentException: IllegalArgumentException) {
- Log.e(
- TAG,
+ logger.error(
illegalArgumentException.message ?: "Failure when handling YubiKey OTP",
- illegalArgumentException.stackTraceToString()
+ illegalArgumentException
)
showToast(R.string.otp_parse_failure, Toast.LENGTH_LONG)
} catch (_: UnsupportedOperationException) {
@@ -111,10 +115,6 @@ class NdefActivity : Activity() {
}
}
- companion object {
- const val TAG = "YubicoAuthenticatorOTPActivity"
- }
-
enum class OtpType {
Otp, Password
}
diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/logging/Log.kt b/android/app/src/main/kotlin/com/yubico/authenticator/logging/Log.kt
index 5d33e0e9..ce11c8a4 100644
--- a/android/app/src/main/kotlin/com/yubico/authenticator/logging/Log.kt
+++ b/android/app/src/main/kotlin/com/yubico/authenticator/logging/Log.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 Yubico.
+ * Copyright (C) 2022-2023 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,16 @@
package com.yubico.authenticator.logging
-import android.util.Log
+import ch.qos.logback.classic.Level
import com.yubico.authenticator.BuildConfig
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
object Log {
+ private val logger = LoggerFactory.getLogger("com.yubico.authenticator")
+
enum class LogLevel {
TRAFFIC,
DEBUG,
@@ -42,34 +47,10 @@ object Log {
LogLevel.INFO
}
- private const val TAG = "yubico-authenticator"
-
- @Suppress("unused")
- fun t(tag: String, message: String, error: String? = null) {
- log(LogLevel.TRAFFIC, tag, message, error)
+ init {
+ setLevel(level)
}
- @Suppress("unused")
- fun d(tag: String, message: String, error: String? = null) {
- log(LogLevel.DEBUG, tag, message, error)
- }
-
- @Suppress("unused")
- fun i(tag: String, message: String, error: String? = null) {
- log(LogLevel.INFO, tag, message, error)
- }
-
- @Suppress("unused")
- fun w(tag: String, message: String, error: String? = null) {
- log(LogLevel.WARNING, tag, message, error)
- }
-
- @Suppress("unused")
- fun e(tag: String, message: String, error: String? = null) {
- log(LogLevel.ERROR, tag, message, error)
- }
-
- @Suppress("unused")
fun log(level: LogLevel, loggerName: String, message: String, error: String?) {
if (level < this.level) {
return
@@ -79,27 +60,33 @@ object Log {
buffer.removeAt(0)
}
- val logMessage = "[$loggerName] ${level.name}: $message".also {
- buffer.add(it)
- }
+ val logMessage = (if (error == null)
+ "[$loggerName] ${level.name}: $message"
+ else
+ "[$loggerName] ${level.name}: $message (err: $error)"
+ ).also {
+ buffer.add(it)
+ }
when (level) {
- LogLevel.TRAFFIC -> Log.v(TAG, logMessage)
- LogLevel.DEBUG -> Log.d(TAG, logMessage)
- LogLevel.INFO -> Log.i(TAG, logMessage)
- LogLevel.WARNING -> Log.w(TAG, logMessage)
- LogLevel.ERROR -> Log.e(TAG, logMessage)
- }
-
- error?.let {
- Log.e(TAG, "[$loggerName] ${level.name}(details): $error".also {
- buffer.add(it)
- })
+ LogLevel.TRAFFIC -> logger.trace(logMessage)
+ LogLevel.DEBUG -> logger.debug(logMessage)
+ LogLevel.INFO -> logger.info(logMessage)
+ LogLevel.WARNING -> logger.warn(logMessage)
+ LogLevel.ERROR -> logger.error(logMessage)
}
}
- @Suppress("unused")
fun setLevel(newLevel: LogLevel) {
level = newLevel
+
+ val root = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as ch.qos.logback.classic.Logger
+ root.level = when (newLevel) {
+ LogLevel.TRAFFIC -> Level.TRACE
+ LogLevel.DEBUG -> Level.DEBUG
+ LogLevel.INFO -> Level.INFO
+ LogLevel.WARNING -> Level.WARN
+ LogLevel.ERROR -> Level.ERROR
+ }
}
}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/oath/AppLinkMethodChannel.kt b/android/app/src/main/kotlin/com/yubico/authenticator/oath/AppLinkMethodChannel.kt
index 7cb9cd4b..3012601a 100644
--- a/android/app/src/main/kotlin/com/yubico/authenticator/oath/AppLinkMethodChannel.kt
+++ b/android/app/src/main/kotlin/com/yubico/authenticator/oath/AppLinkMethodChannel.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 Yubico.
+ * Copyright (C) 2022-2023 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,25 +17,26 @@
package com.yubico.authenticator.oath
import android.net.Uri
+
import androidx.annotation.UiThread
-import com.yubico.authenticator.logging.Log
+
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
+
import org.json.JSONObject
+import org.slf4j.LoggerFactory
+
class AppLinkMethodChannel(messenger: BinaryMessenger) {
private val methodChannel = MethodChannel(messenger, "app.link.methods")
+ private val logger = LoggerFactory.getLogger(AppLinkMethodChannel::class.java)
@UiThread
fun handleUri(uri: Uri) {
- Log.t(TAG, "Handling URI: $uri")
+ logger.trace("Handling URI: {}", uri)
methodChannel.invokeMethod(
"handleOtpAuthLink",
JSONObject(mapOf("link" to uri.toString())).toString()
)
}
-
- companion object {
- const val TAG = "AppLinkMethodChannel"
- }
}
\ No newline at end of file
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 c550ea1e..ab88b531 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
@@ -61,6 +61,7 @@ import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.*
import kotlinx.serialization.encodeToString
+import org.slf4j.LoggerFactory
import java.net.URI
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
@@ -77,7 +78,6 @@ class OathManager(
private val appPreferences: AppPreferences,
) : AppContextManager {
companion object {
- const val TAG = "OathManager"
const val NFC_DATA_CLEANUP_DELAY = 30L * 1000 // 30s
val OTP_AID = byteArrayOf(0xa0.toByte(), 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x01)
}
@@ -98,6 +98,8 @@ class OathManager(
)
}
+ private val logger = LoggerFactory.getLogger(OathManager::class.java)
+
@TargetApi(Build.VERSION_CODES.M)
private fun createKeyStoreProviderM(): KeyProvider = KeyStoreProvider()
@@ -117,7 +119,7 @@ class OathManager(
// cancel any pending actions, except for addToAny
if (!addToAny) {
pendingAction?.let {
- Log.d(TAG, "Cancelling pending action/closing nfc dialog.")
+ logger.debug("Cancelling pending action/closing nfc dialog.")
it.invoke(Result.failure(CancellationException()))
coroutineScope.launch {
dialogManager.closeDialog()
@@ -134,7 +136,7 @@ class OathManager(
if (canInvoke) {
if (appViewModel.connectedYubiKey.value == null) {
// no USB YubiKey is connected, reset known data on resume
- Log.d(TAG, "Removing NFC data after resume.")
+ logger.debug("Removing NFC data after resume.")
appViewModel.setDeviceInfo(null)
oathViewModel.setSessionState(null)
}
@@ -169,7 +171,7 @@ class OathManager(
refreshJob = coroutineScope.launch {
val delayMs = earliest - now
- Log.d(TAG, "Will execute refresh in ${delayMs}ms")
+ logger.debug("Will execute refresh in {}ms", delayMs)
if (delayMs > 0) {
delay(delayMs)
}
@@ -177,9 +179,9 @@ class OathManager(
if (currentState.isAtLeast(Lifecycle.State.RESUMED)) {
requestRefresh()
} else {
- Log.d(
- TAG,
- "Cannot run credential refresh in current lifecycle state: $currentState"
+ logger.debug(
+ "Cannot run credential refresh in current lifecycle state: {}",
+ currentState
)
}
}
@@ -257,7 +259,7 @@ class OathManager(
try {
oathViewModel.updateCredentials(calculateOathCodes(session))
} catch (error: Exception) {
- Log.e(TAG, "Failed to refresh codes", error.toString())
+ logger.error("Failed to refresh codes", error)
}
}
} else {
@@ -296,7 +298,7 @@ class OathManager(
try {
SmartCardProtocol(connection).select(OTP_AID)
} catch (e: Exception) {
- Log.e(TAG, "Failed to recognize this OATH device.")
+ logger.error("Failed to recognize this OATH device.")
// we know this is NFC device and it supports OATH
val oathCapabilities = Capabilities(nfc = 0x20)
appViewModel.setDeviceInfo(
@@ -325,25 +327,24 @@ class OathManager(
}
}
- Log.d(
- TAG,
+ logger.debug(
"Successfully read Oath session info (and credentials if unlocked) from connected key"
)
} catch (e: Exception) {
// OATH not enabled/supported, try to get DeviceInfo over other USB interfaces
- Log.e(TAG, "Failed to connect to CCID", e.toString())
+ logger.error("Failed to connect to CCID", e)
if (device.transport == Transport.USB || e is ApplicationNotAvailableException) {
val deviceInfo = try {
getDeviceInfo(device)
} catch (e: IllegalArgumentException) {
- Log.d(TAG, "Device was not recognized")
+ logger.debug("Device was not recognized")
UnknownDevice.copy(isNfc = device.transport == Transport.NFC)
} catch (e: Exception) {
- Log.d(TAG, "Failure getting device info: ${e.message}")
+ logger.error("Failure getting device info", e)
null
}
- Log.d(TAG, "Setting device info: $deviceInfo")
+ logger.debug("Setting device info: {}", deviceInfo)
appViewModel.setDeviceInfo(deviceInfo)
}
@@ -377,7 +378,7 @@ class OathManager(
Code.from(code)
)
- Log.d(TAG, "Added cred $credential")
+ logger.debug("Added cred {}", credential)
jsonSerializer.encodeToString(addedCred)
}
}
@@ -431,7 +432,7 @@ class OathManager(
session.setAccessKey(accessKey)
keyManager.addKey(session.deviceId, accessKey, false)
oathViewModel.setSessionState(Session(session, false))
- Log.d(TAG, "Successfully set password")
+ logger.debug("Successfully set password")
NULL
}
@@ -443,7 +444,7 @@ class OathManager(
session.deleteAccessKey()
keyManager.removeKey(session.deviceId)
oathViewModel.setSessionState(Session(session, false))
- Log.d(TAG, "Successfully unset password")
+ logger.debug("Successfully unset password")
return@useOathSession NULL
}
}
@@ -452,7 +453,7 @@ class OathManager(
private suspend fun forgetPassword(): String {
keyManager.clearAll()
- Log.d(TAG, "Cleared all keys.")
+ logger.debug("Cleared all keys.")
oathViewModel.sessionState.value?.let {
oathViewModel.setSessionState(
it.copy(
@@ -516,7 +517,7 @@ class OathManager(
oathViewModel.updateCredentials(calculateOathCodes(session))
} catch (apduException: ApduException) {
if (apduException.sw == SW.SECURITY_CONDITION_NOT_SATISFIED) {
- Log.d(TAG, "Handled oath credential refresh on locked session.")
+ logger.debug("Handled oath credential refresh on locked session.")
oathViewModel.setSessionState(
Session(
session,
@@ -524,10 +525,9 @@ class OathManager(
)
)
} else {
- Log.e(
- TAG,
+ logger.error(
"Unexpected sw when refreshing oath credentials",
- apduException.message
+ apduException
)
}
}
@@ -543,7 +543,7 @@ class OathManager(
Credential(credential, session.deviceId),
code
)
- Log.d(TAG, "Code calculated $code")
+ logger.debug("Code calculated {}", code)
jsonSerializer.encodeToString(code)
}
@@ -679,7 +679,7 @@ class OathManager(
})
}
dialogManager.showDialog(Icon.NFC, "Tap your key", title) {
- Log.d(TAG, "Cancelled Dialog $title")
+ logger.debug("Cancelled Dialog {}", title)
pendingAction?.invoke(Result.failure(CancellationException()))
pendingAction = null
}
diff --git a/android/app/src/main/kotlin/com/yubico/authenticator/yubikit/DeviceInfoHelper.kt b/android/app/src/main/kotlin/com/yubico/authenticator/yubikit/DeviceInfoHelper.kt
index 433f7b5e..9a985c92 100644
--- a/android/app/src/main/kotlin/com/yubico/authenticator/yubikit/DeviceInfoHelper.kt
+++ b/android/app/src/main/kotlin/com/yubico/authenticator/yubikit/DeviceInfoHelper.kt
@@ -17,8 +17,6 @@
package com.yubico.authenticator.yubikit
import com.yubico.authenticator.device.Info
-import com.yubico.authenticator.logging.Log
-import com.yubico.authenticator.oath.OathManager
import com.yubico.authenticator.compatUtil
import com.yubico.yubikit.android.transport.nfc.NfcYubiKeyDevice
import com.yubico.yubikit.android.transport.usb.UsbYubiKeyDevice
@@ -29,22 +27,25 @@ import com.yubico.yubikit.core.smartcard.SmartCardConnection
import com.yubico.yubikit.management.DeviceInfo
import com.yubico.yubikit.support.DeviceUtil
+import org.slf4j.LoggerFactory
+
suspend fun getDeviceInfo(device: YubiKeyDevice): Info {
val pid = (device as? UsbYubiKeyDevice)?.pid
+ val logger = LoggerFactory.getLogger("getDeviceInfo")
val deviceInfo = runCatching {
device.withConnection { DeviceUtil.readInfo(it, pid) }
}.recoverCatching { t ->
- Log.d(OathManager.TAG, "Smart card connection not available: ${t.message}")
+ logger.debug("Smart card connection not available: {}", t.message)
device.withConnection { DeviceUtil.readInfo(it, pid) }
}.recoverCatching { t ->
- Log.d(OathManager.TAG, "OTP connection not available: ${t.message}")
+ logger.debug("OTP connection not available: {}", t.message)
device.withConnection { DeviceUtil.readInfo(it, pid) }
}.recoverCatching { t ->
- Log.d(OathManager.TAG, "FIDO connection not available: ${t.message}")
+ logger.debug("FIDO connection not available: {}", t.message)
return SkyHelper(compatUtil).getDeviceInfo(device)
}.getOrElse {
- Log.e(OathManager.TAG, "Failed to recognize device: ${it.message}")
+ logger.debug("Failed to recognize device: {}", it.message)
throw it
}
diff --git a/android/build.gradle b/android/build.gradle
index abc6dde0..c91fe98b 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -24,7 +24,7 @@ allprojects {
targetSdkVersion = 33
compileSdkVersion = 33
- yubiKitVersion = "2.2.0"
+ yubiKitVersion = "2.3.0"
junitVersion = "4.13.2"
mockitoVersion = "5.3.1"
}