diff --git a/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/transport/screenlock/ScreenLockTransportHandler.kt b/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/transport/screenlock/ScreenLockTransportHandler.kt index ff72cf5569..f16518da2e 100644 --- a/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/transport/screenlock/ScreenLockTransportHandler.kt +++ b/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/transport/screenlock/ScreenLockTransportHandler.kt @@ -259,13 +259,18 @@ class ScreenLockTransportHandler(private val activity: FragmentActivity, callbac override fun shouldBeUsedInstantly(options: RequestOptions): Boolean { if (options.type != RequestOptionsType.SIGN) return false - for (descriptor in options.signOptions.allowList.orEmpty()) { + // If there is an allow list, it means we try to login for a defined user. + // So if we have one of the allowed keys to login with the screen lock, we use it. + // + // We DON'T want to use instant connection if the allowList is empty, as the user + // may want to login with different user accounts, maybe on a hardware key + options.signOptions.allowList?.forEach { try { - val (type, data) = CredentialId.decodeTypeAndData(descriptor.id) + val (type, data) = CredentialId.decodeTypeAndData(it.id) if (type == 1.toByte() && store.containsKey(options.rpId, data)) { return true } - } catch (e: Exception) { + } catch (_: Exception) { // Ignore } } diff --git a/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/ui/AuthenticatorActivity.kt b/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/ui/AuthenticatorActivity.kt index 74bddc2c06..3b751aee12 100644 --- a/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/ui/AuthenticatorActivity.kt +++ b/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/ui/AuthenticatorActivity.kt @@ -6,8 +6,6 @@ package org.microg.gms.fido.core.ui import android.content.Intent -import android.graphics.Color -import android.graphics.drawable.ColorDrawable import android.os.Build.VERSION.SDK_INT import android.os.Bundle import android.util.Base64 @@ -24,7 +22,6 @@ import com.google.android.gms.fido.fido2.api.common.AuthenticationExtensionsPrfO import com.google.android.gms.fido.fido2.api.common.ErrorCode.* import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Job -import org.microg.gms.common.GmsService import org.microg.gms.fido.core.* import org.microg.gms.fido.core.transport.Transport import org.microg.gms.fido.core.transport.Transport.* @@ -37,6 +34,7 @@ import org.microg.gms.fido.core.transport.usb.UsbTransportHandler import org.microg.gms.utils.getApplicationLabel import org.microg.gms.utils.getFirstSignatureDigest import org.microg.gms.utils.toBase64 +import androidx.core.graphics.drawable.toDrawable const val TAG = "FidoUi" @@ -54,8 +52,6 @@ class AuthenticatorActivity : AppCompatActivity(), TransportHandlerCallback { else -> null } - private val service: GmsService - get() = GmsService.byServiceId(intent.getIntExtra(KEY_SERVICE, GmsService.UNKNOWN.SERVICE_ID)) private val database by lazy { Database(this) } private val transportHandlers by lazy { setOfNotNull( @@ -95,19 +91,6 @@ class AuthenticatorActivity : AppCompatActivity(), TransportHandlerCallback { Log.d(TAG, "onCreate caller=$callerPackage options=$options") - val requiresPrivilege = - options is BrowserRequestOptions && !database.isPrivileged(callerPackage, callerSignature) - - // Check if we can directly open screen lock handling - if (!requiresPrivilege) { - val instantTransport = transportHandlers.firstOrNull { it.isSupported && it.shouldBeUsedInstantly(options) } - if (instantTransport != null && instantTransport.transport in INSTANT_SUPPORTED_TRANSPORTS) { - window.setBackgroundDrawable(ColorDrawable(0)) - window.statusBarColor = Color.TRANSPARENT - setTheme(org.microg.gms.base.core.R.style.Theme_Translucent) - } - } - setTheme(androidx.appcompat.R.style.Theme_AppCompat_DayNight_NoActionBar) setContentView(R.layout.fido_authenticator_activity) @@ -136,10 +119,15 @@ class AuthenticatorActivity : AppCompatActivity(), TransportHandlerCallback { Log.d(TAG, "origin=$origin, appName=$appName") // Check if we can directly open screen lock handling + // If the request contains an allow list, the request is for a dedicated account. + // If we have one of the allowed keys we instant login + // Else, the user must be able to choose if (!requiresPrivilege && allowInstant) { - val instantTransport = transportHandlers.firstOrNull { it.isSupported && it.shouldBeUsedInstantly(options) } - if (instantTransport != null && instantTransport.transport in INSTANT_SUPPORTED_TRANSPORTS) { - startTransportHandling(instantTransport.transport, true) + transportHandlers.firstOrNull { + it.isSupported && it.shouldBeUsedInstantly(options) + }?.let { + window.setBackgroundDrawable(0.toDrawable()) + startTransportHandling(it.transport, true) return } } @@ -154,7 +142,6 @@ class AuthenticatorActivity : AppCompatActivity(), TransportHandlerCallback { val next = if (!requiresPrivilege) { val knownRegistrationTransports = mutableSetOf() val allowedTransports = mutableSetOf() - val localSavedUserKey = mutableSetOf() if (options.type == RequestOptionsType.SIGN) { for (descriptor in options.signOptions.allowList.orEmpty()) { val knownTransport = database.getKnownRegistrationTransport(options.rpId, descriptor.id.toBase64(Base64.URL_SAFE, Base64.NO_WRAP, Base64.NO_PADDING)) @@ -177,13 +164,11 @@ class AuthenticatorActivity : AppCompatActivity(), TransportHandlerCallback { } } } - database.getKnownRegistrationInfo(options.rpId).forEach { localSavedUserKey.add(it.userJson) } } val preselectedTransport = knownRegistrationTransports.singleOrNull() ?: allowedTransports.singleOrNull() if (database.wasUsed()) { - if (localSavedUserKey.isNotEmpty()) { - R.id.signInSelectionFragment - } else when (preselectedTransport) { + when (preselectedTransport) { + SCREEN_LOCK -> R.id.signInSelectionFragment USB -> R.id.usbFragment NFC -> R.id.nfcFragment else -> R.id.transportSelectionFragment @@ -358,7 +343,6 @@ class AuthenticatorActivity : AppCompatActivity(), TransportHandlerCallback { const val KEY_CALLER = "caller" val IMPLEMENTED_TRANSPORTS = setOf(USB, SCREEN_LOCK, NFC) - val INSTANT_SUPPORTED_TRANSPORTS = setOf(SCREEN_LOCK) } } diff --git a/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/ui/TransportSelectionFragment.kt b/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/ui/TransportSelectionFragment.kt index 384bd1fd92..5cf4122c7e 100644 --- a/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/ui/TransportSelectionFragment.kt +++ b/play-services-fido/core/src/main/kotlin/org/microg/gms/fido/core/ui/TransportSelectionFragment.kt @@ -10,9 +10,10 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.navigation.fragment.findNavController +import com.google.android.gms.fido.fido2.api.common.BrowserPublicKeyCredentialRequestOptions +import com.google.android.gms.fido.fido2.api.common.PublicKeyCredentialRequestOptions import org.microg.gms.fido.core.R import org.microg.gms.fido.core.databinding.FidoTransportSelectionFragmentBinding -import org.microg.gms.fido.core.transport.Transport import org.microg.gms.fido.core.transport.Transport.SCREEN_LOCK class TransportSelectionFragment : AuthenticatorActivityFragment() { @@ -31,7 +32,15 @@ class TransportSelectionFragment : AuthenticatorActivityFragment() { findNavController().navigate(R.id.openUsbFragment, arguments.withIsFirst(false)) } binding.setOnScreenLockClick { - startTransportHandling(SCREEN_LOCK) + if (options is PublicKeyCredentialRequestOptions || + options is BrowserPublicKeyCredentialRequestOptions) { + findNavController().navigate( + R.id.signInSelectionFragment, + arguments.withIsFirst(false) + ) + } else { + startTransportHandling(SCREEN_LOCK) + } } return binding.root }