mirror of
https://github.com/bitwarden/android.git
synced 2026-03-11 20:54:58 -05:00
BITAU-112 Support deep link into add item flow from Authenticator app (#4128)
This commit is contained in:
@@ -49,13 +49,8 @@ interface IAuthenticatorBridgeService {
|
||||
// Add TOTP Item
|
||||
// ==============
|
||||
|
||||
// Returns an intent that can be launched to navigate the user to the add Totp item flow
|
||||
// in the main password manager app.
|
||||
Intent createAddTotpLoginItemIntent();
|
||||
|
||||
// Give the given TOTP item data to the main Bitwarden app before launching the add TOTP
|
||||
// item flow. This should be called before launching the intent returned from
|
||||
// createAddTotpLoginItemIntent().
|
||||
void setPendingAddTotpLoginItemData(in EncryptedAddTotpLoginItemData data);
|
||||
// Start the add TOTP item flow in the main Bitwarden app with the given data.
|
||||
// Returns true if the flow was successfully launched and false otherwise.
|
||||
boolean startAddTotpLoginItemFlow(in EncryptedAddTotpLoginItemData data);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.bitwarden.authenticatorbridge.manager
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import com.bitwarden.authenticatorbridge.IAuthenticatorBridgeService
|
||||
import com.bitwarden.authenticatorbridge.manager.model.AccountSyncState
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@@ -14,4 +16,12 @@ interface AuthenticatorBridgeManager {
|
||||
* State flow representing the current [AccountSyncState].
|
||||
*/
|
||||
val accountSyncStateFlow: StateFlow<AccountSyncState>
|
||||
|
||||
/**
|
||||
* Start the add TOTP item flow in the main Bitwarden app with the given data.
|
||||
*
|
||||
* @param totpUri TOTP URI to add to the main Bitwarden app.
|
||||
* @return true if the flow was successfully launched, false otherwise.
|
||||
*/
|
||||
fun startAddTotpLoginItemFlow(totpUri: String): Boolean
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.content.ServiceConnection
|
||||
import android.content.pm.PackageManager.NameNotFoundException
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.DefaultLifecycleObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
@@ -14,11 +15,13 @@ import com.bitwarden.authenticatorbridge.IAuthenticatorBridgeService
|
||||
import com.bitwarden.authenticatorbridge.manager.model.AccountSyncState
|
||||
import com.bitwarden.authenticatorbridge.manager.model.AuthenticatorBridgeConnectionType
|
||||
import com.bitwarden.authenticatorbridge.manager.util.toPackageName
|
||||
import com.bitwarden.authenticatorbridge.model.AddTotpLoginItemData
|
||||
import com.bitwarden.authenticatorbridge.model.EncryptedSharedAccountData
|
||||
import com.bitwarden.authenticatorbridge.provider.AuthenticatorBridgeCallbackProvider
|
||||
import com.bitwarden.authenticatorbridge.provider.StubAuthenticatorBridgeCallbackProvider
|
||||
import com.bitwarden.authenticatorbridge.provider.SymmetricKeyStorageProvider
|
||||
import com.bitwarden.authenticatorbridge.util.decrypt
|
||||
import com.bitwarden.authenticatorbridge.util.encrypt
|
||||
import com.bitwarden.authenticatorbridge.util.isBuildVersionBelow
|
||||
import com.bitwarden.authenticatorbridge.util.toFingerprint
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -103,6 +106,21 @@ internal class AuthenticatorBridgeManagerImpl(
|
||||
)
|
||||
}
|
||||
|
||||
override fun startAddTotpLoginItemFlow(totpUri: String): Boolean =
|
||||
bridgeService
|
||||
?.safeCall {
|
||||
// Grab symmetric key data from local storage:
|
||||
val symmetricKey = symmetricKeyStorageProvider.symmetricKey ?: return@safeCall false
|
||||
// Encrypt the given URI:
|
||||
val addTotpData = AddTotpLoginItemData(totpUri).encrypt(symmetricKey).getOrThrow()
|
||||
return@safeCall this.startAddTotpLoginItemFlow(addTotpData)
|
||||
}
|
||||
?.fold(
|
||||
onFailure = { false },
|
||||
onSuccess = { true }
|
||||
)
|
||||
?: false
|
||||
|
||||
private fun bindService() {
|
||||
if (isBuildVersionBelow(Build.VERSION_CODES.S)) {
|
||||
mutableSharedAccountsStateFlow.value = AccountSyncState.OsVersionNotSupported
|
||||
@@ -119,11 +137,17 @@ internal class AuthenticatorBridgeManagerImpl(
|
||||
)
|
||||
}
|
||||
|
||||
val flags = if (isBuildVersionBelow(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) {
|
||||
Context.BIND_AUTO_CREATE
|
||||
} else {
|
||||
Context.BIND_AUTO_CREATE or Context.BIND_ALLOW_ACTIVITY_STARTS
|
||||
}
|
||||
|
||||
val isBound = try {
|
||||
applicationContext.bindService(
|
||||
intent,
|
||||
bridgeServiceConnection,
|
||||
Context.BIND_AUTO_CREATE,
|
||||
flags,
|
||||
)
|
||||
} catch (e: SecurityException) {
|
||||
unbindService()
|
||||
|
||||
@@ -118,7 +118,7 @@ internal fun AddTotpLoginItemData.encrypt(
|
||||
*
|
||||
* @param symmetricEncryptionKeyData Symmetric key used for decryption.
|
||||
*/
|
||||
internal fun EncryptedAddTotpLoginItemData.decrypt(
|
||||
fun EncryptedAddTotpLoginItemData.decrypt(
|
||||
symmetricEncryptionKeyData: SymmetricEncryptionKeyData,
|
||||
): Result<AddTotpLoginItemData> = runCatching {
|
||||
val encodedKey = symmetricEncryptionKeyData
|
||||
|
||||
Reference in New Issue
Block a user