diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java index 9be104cc2..b23c3d1fa 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableApi.java @@ -135,7 +135,7 @@ IterableAuthManager getAuthManager() { return authManager; } - @NonNull + @Nullable IterableKeychain getKeychain() { if (keychain == null) { try { @@ -350,15 +350,25 @@ private String getDeviceId() { } private void storeAuthData() { - getKeychain().saveEmail(_email); - getKeychain().saveUserId(_userId); - getKeychain().saveAuthToken(_authToken); + IterableKeychain iterableKeychain = getKeychain(); + if (iterableKeychain != null) { + iterableKeychain.saveEmail(_email); + iterableKeychain.saveUserId(_userId); + iterableKeychain.saveAuthToken(_authToken); + } else { + IterableLogger.e(TAG, "Shared preference creation failed. "); + } } private void retrieveEmailAndUserId() { - _email = getKeychain().getEmail(); - _userId = getKeychain().getUserId(); - _authToken = getKeychain().getAuthToken(); + IterableKeychain iterableKeychain = getKeychain(); + if (iterableKeychain != null) { + _email = iterableKeychain.getEmail(); + _userId = iterableKeychain.getUserId(); + _authToken = iterableKeychain.getAuthToken(); + } else { + IterableLogger.e(TAG, "retrieveEmailAndUserId: Shared preference creation failed. Could not retrieve email/userId"); + } if (config.authHandler != null) { if (_authToken != null) { @@ -370,10 +380,6 @@ private void retrieveEmailAndUserId() { } } - private void updateSDKVersion() { - - } - private class IterableApiAuthProvider implements IterableApiClient.AuthProvider { @Nullable @Override @@ -507,8 +513,6 @@ public static void initialize(@NonNull Context context, @NonNull String apiKey, sharedInstance.config = new IterableConfig.Builder().build(); } - sharedInstance.updateSDKVersion(); - sharedInstance.retrieveEmailAndUserId(); IterableActivityMonitor.getInstance().registerLifecycleCallbacks(context); diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java b/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java index 9c90a2c96..73a8e8397 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableConfig.java @@ -237,6 +237,12 @@ public Builder setAllowedProtocols(@NonNull String[] allowedProtocols) { return this; } + /** + * Set whether the SDK should enforce encryption. If set to `true`, the SDK will not use fallback mechanism + * of storing data in un-encrypted shared preferences if encrypted database is not available. Set this to `true` + * if PII confidentiality is a concern for your app. + * @param encryptionEnforced `true` will have the SDK enforce encryption. + */ public Builder setEncryptionEnforced(boolean encryptionEnforced) { this.encryptionEnforced = encryptionEnforced; return this; diff --git a/iterableapi/src/main/java/com/iterable/iterableapi/IterableKeychain.kt b/iterableapi/src/main/java/com/iterable/iterableapi/IterableKeychain.kt index 17e0a705d..ac8d59964 100644 --- a/iterableapi/src/main/java/com/iterable/iterableapi/IterableKeychain.kt +++ b/iterableapi/src/main/java/com/iterable/iterableapi/IterableKeychain.kt @@ -26,7 +26,8 @@ class IterableKeychain { encryptionEnabled = false sharedPrefs = context.getSharedPreferences( IterableConstants.SHARED_PREFS_FILE, - Context.MODE_PRIVATE) + Context.MODE_PRIVATE + ) IterableLogger.v(TAG, "SharedPreferences being used") } else { // See if EncryptedSharedPreferences can be created successfully @@ -39,7 +40,8 @@ class IterableKeychain { encryptedSharedPrefsFileName, masterKeyAlias, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, - EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM) + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM + ) encryptionEnabled = true } catch (e: Exception) { if (encryptionEnforced) { @@ -49,35 +51,16 @@ class IterableKeychain { } else { sharedPrefs = context.getSharedPreferences( IterableConstants.SHARED_PREFS_FILE, - Context.MODE_PRIVATE) + Context.MODE_PRIVATE + ) encryptionEnabled = false } } //Try to migrate data from SharedPreferences to EncryptedSharedPreferences - if(encryptionEnabled) { + if (encryptionEnabled) { migrateAuthDataFromSharedPrefsToKeychain(context) } - - } - val masterKeyAlias = MasterKey.Builder(context) - .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) - .build() - sharedPrefs = try { - EncryptedSharedPreferences.create( - context, - encryptedSharedPrefsFileName, - masterKeyAlias, - EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, - EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM - ) - } catch (e: Exception) { - if (encryptionEnforced) { - IterableLogger.e(TAG, "Error creating EncryptedSharedPreferences", e) - throw e.fillInStackTrace() - } else { - context.getSharedPreferences(encryptedSharedPrefsFileName, Context.MODE_PRIVATE) - } } } @@ -113,17 +96,20 @@ class IterableKeychain { @RequiresApi(api = Build.VERSION_CODES.M) private fun migrateAuthDataFromSharedPrefsToKeychain(context: Context) { - val oldPrefs: SharedPreferences = context.getSharedPreferences( + val oldPrefs: SharedPreferences = context.getSharedPreferences( IterableConstants.SHARED_PREFS_FILE, - Context.MODE_PRIVATE) + Context.MODE_PRIVATE + ) val sharedPrefsEmail = oldPrefs.getString(IterableConstants.SHARED_PREFS_EMAIL_KEY, null) val sharedPrefsUserId = oldPrefs.getString(IterableConstants.SHARED_PREFS_USERID_KEY, null) - val sharedPrefsAuthToken = oldPrefs.getString(IterableConstants.SHARED_PREFS_AUTH_TOKEN_KEY, null) + val sharedPrefsAuthToken = + oldPrefs.getString(IterableConstants.SHARED_PREFS_AUTH_TOKEN_KEY, null) val editor: SharedPreferences.Editor = oldPrefs.edit() if (getEmail() == null && sharedPrefsEmail != null) { saveEmail(sharedPrefsEmail) editor.remove(IterableConstants.SHARED_PREFS_EMAIL_KEY) - IterableLogger.v(TAG, + IterableLogger.v( + TAG, "UPDATED: migrated email from SharedPreferences to IterableKeychain" ) } else if (sharedPrefsEmail != null) { @@ -132,7 +118,8 @@ class IterableKeychain { if (getUserId() == null && sharedPrefsUserId != null) { saveUserId(sharedPrefsUserId) editor.remove(IterableConstants.SHARED_PREFS_USERID_KEY) - IterableLogger.v(TAG, + IterableLogger.v( + TAG, "UPDATED: migrated userId from SharedPreferences to IterableKeychain" ) } else if (sharedPrefsUserId != null) { @@ -141,7 +128,8 @@ class IterableKeychain { if (getAuthToken() == null && sharedPrefsAuthToken != null) { saveAuthToken(sharedPrefsAuthToken) editor.remove(IterableConstants.SHARED_PREFS_AUTH_TOKEN_KEY) - IterableLogger.v(TAG, + IterableLogger.v( + TAG, "UPDATED: migrated authToken from SharedPreferences to IterableKeychain" ) } else if (sharedPrefsAuthToken != null) {