Skip to content

Commit

Permalink
PIA-684: Introduce keychain migration logic (#4)
Browse files Browse the repository at this point in the history
* introduce keychain migration logic

* re-use Android setting rather than duplicate it
  • Loading branch information
kp-juan-docal authored Oct 6, 2023
1 parent 773ae68 commit 29c0a8c
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ internal actual object SecureSettingsProvider {
get() = AccountContextProvider.applicationContext?.let { context ->
EncryptedSettingsFactory(context).create(SHARED_PREFS_NAME)
}

// No change. The deprecated settings is for iOS only due to
// its constructor kSecAttrAccessible change.
actual val deprecatedSettings: Settings?
get() = settings
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import com.russhwolf.settings.Settings
internal object SecureSettingsPersistence : AccountPersistence {

private val settings: Settings? = SecureSettingsProvider.settings
private val deprecatedSettings: Settings? = SecureSettingsProvider.deprecatedSettings

override fun persistApiTokenResponse(apiToken: ApiTokenResponse) {
migrateTokens()
settings?.putString(
Account.API_TOKEN_KEY,
Account.json.encodeToString(
Expand All @@ -21,6 +23,7 @@ internal object SecureSettingsPersistence : AccountPersistence {
}

override fun persistVpnTokenResponse(vpnToken: VpnTokenResponse) {
migrateTokens()
settings?.putString(
Account.VPN_TOKEN_KEY,
Account.json.encodeToString(
Expand All @@ -30,21 +33,37 @@ internal object SecureSettingsPersistence : AccountPersistence {
)
}

override fun apiTokenResponse(): ApiTokenResponse? =
settings?.getStringOrNull(Account.API_TOKEN_KEY)?.let {
override fun apiTokenResponse(): ApiTokenResponse? {
migrateTokens()
return settings?.getStringOrNull(Account.API_TOKEN_KEY)?.let {
Account.json.decodeFromString(ApiTokenResponse.serializer(), it)
}
}

override fun vpnTokenResponse(): VpnTokenResponse? =
settings?.getStringOrNull(Account.VPN_TOKEN_KEY)?.let {
override fun vpnTokenResponse(): VpnTokenResponse? {
migrateTokens()
return settings?.getStringOrNull(Account.VPN_TOKEN_KEY)?.let {
Account.json.decodeFromString(VpnTokenResponse.serializer(), it)
}
}

override fun clearApiTokenResponse() {
settings?.remove(Account.API_TOKEN_KEY)
deprecatedSettings?.remove(Account.API_TOKEN_KEY)
}

override fun clearVpnTokenResponse() {
settings?.remove(Account.VPN_TOKEN_KEY)
deprecatedSettings?.remove(Account.VPN_TOKEN_KEY)
}

// region private
private fun migrateTokens() {
deprecatedSettings?.keys?.forEach {
val value = deprecatedSettings.getString(it, "")
deprecatedSettings.remove(it)
settings?.putString(it, value)
}
}
// endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ package com.privateinternetaccess.account.internals.persistency.secureSettings
import com.russhwolf.settings.Settings

internal expect object SecureSettingsProvider {
val deprecatedSettings: Settings?
val settings: Settings?
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,10 @@ internal actual object SecureSettingsProvider {
kSecAttrService to CFBridgingRetain(KEYCHAIN_NAME),
kSecAttrAccessible to kSecAttrAccessibleAlways
)

@OptIn(ExperimentalSettingsImplementation::class, ExperimentalForeignApi::class)
actual val deprecatedSettings: Settings?
get() = KeychainSettings(
kSecAttrService to CFBridgingRetain(KEYCHAIN_NAME)
)
}
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
id("com.android.library").version("7.3.1").apply(false)
kotlin("multiplatform").version("1.9.0").apply(false)
kotlin("plugin.serialization").version("1.9.0").apply(false)
kotlin("multiplatform").version("1.9.10").apply(false)
kotlin("plugin.serialization").version("1.9.10").apply(false)
}

tasks.register("clean", Delete::class) {
Expand Down

0 comments on commit 29c0a8c

Please sign in to comment.