Add backup rules for CredentialIdentityStore kotlin implementation (#520)

This commit is contained in:
Leendert de Borst
2025-10-27 10:28:52 +01:00
parent 9ec245c102
commit f97efea681
4 changed files with 66 additions and 1 deletions

View File

@@ -12,7 +12,7 @@
<data android:scheme="https"/>
</intent>
</queries>
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true" android:usesCleartextTraffic="true" android:localeConfig="@xml/locales_config" android:networkSecurityConfig="@xml/network_security_config">
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:fullBackupContent="@xml/backup_rules" android:dataExtractionRules="@xml/data_extraction_rules" android:theme="@style/AppTheme" android:supportsRtl="true" android:usesCleartextTraffic="true" android:localeConfig="@xml/locales_config" android:networkSecurityConfig="@xml/network_security_config">
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>

View File

@@ -16,6 +16,12 @@ import org.json.JSONObject
* This class stores passkey metadata (rpId, userName, displayName, credentialId, userHandle)
* in SharedPreferences so that passkeys can be displayed without unlocking the vault.
*
* Security features:
* - Uses MODE_PRIVATE for app-private storage (no other apps can access)
* - Excluded from device backups (see backup_rules.xml and data_extraction_rules.xml)
* - Contains no passwords, only metadata (usernames, rpIds, displayNames)
* - Cleared when credential provider is disabled by user
*
* Similar to iOS ASCredentialIdentityStore, but using SharedPreferences as Android's
* Credential Manager API doesn't provide a system-level identity store.
*/
@@ -41,6 +47,8 @@ class CredentialIdentityStore private constructor(context: Context) {
}
}
// MODE_PRIVATE ensures only this app can access the data
// Backup exclusion rules prevent data from being backed up
private val prefs: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
/**
@@ -154,6 +162,21 @@ class CredentialIdentityStore private constructor(context: Context) {
.apply()
}
/**
* Check if the credential identity store is empty.
* This is used to determine if initial sync is needed.
* @return true if the store has no credential identities
*/
fun isStoreEmpty(): Boolean {
return try {
val jsonString = prefs.getString(KEY_PASSKEY_IDENTITIES, null)
jsonString == null || JSONArray(jsonString).length() == 0
} catch (e: Exception) {
Log.e(TAG, "Error checking if store is empty", e)
true // Assume empty if we can't read
}
}
/**
* Create a PasskeyIdentity from a Passkey and its parent Credential.
*/

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Backup rules for Android API < 31 (Android 11 and below).
Excludes sensitive credential identity data from device backups.
The credential_identities file stores user metadata (usernames, email addresses, service names)
that should not leave the device, matching iOS ASCredentialIdentityStore behavior which
explicitly excludes its data from device backups.
Security rationale:
- Contains sensitive user information (though no passwords)
- Should remain device-local for privacy
- Can be re-synced from vault on new device
-->
<full-backup-content>
<!-- Exclude the credential identity store from backups -->
<exclude domain="sharedpref" path="credential_identities.xml"/>
</full-backup-content>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Data extraction rules for Android API 31+ (Android 12 and above).
Excludes sensitive credential identity data from cloud backups and device transfers.
The credential_identities file stores user metadata (usernames, email addresses, service names)
that should not leave the device, matching iOS ASCredentialIdentityStore behavior which
explicitly excludes its data from device backups.
Security rationale:
- Contains sensitive user information (though no passwords)
- Should remain device-local for privacy
- Can be re-synced from vault on new device
-->
<data-extraction-rules>
<cloud-backup>
<!-- Exclude credential identity store from cloud backups -->
<exclude domain="sharedpref" path="credential_identities.xml"/>
</cloud-backup>
<device-transfer>
<!-- Exclude credential identity store from device-to-device transfers -->
<exclude domain="sharedpref" path="credential_identities.xml"/>
</device-transfer>
</data-extraction-rules>