Skip to content

Commit ab600a5

Browse files
authored
Merge pull request #565 from Iterable/jay/MOB-4436-encrypt-auth-data
[MOB-4436] encrypt auth data
2 parents e6f5ac1 + ff2db11 commit ab600a5

File tree

4 files changed

+108
-17
lines changed

4 files changed

+108
-17
lines changed

swift-sdk/Constants.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ enum Const {
6060
static let serviceName = "itbl_keychain"
6161

6262
enum Key {
63+
static let email = "itbl_email"
64+
static let userId = "itbl_userid"
6365
static let authToken = "itbl_auth_token"
6466
}
6567
}

swift-sdk/Internal/IterableKeychain.swift

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,56 @@
55
import Foundation
66

77
class IterableKeychain {
8+
var email: String? {
9+
get {
10+
let data = wrapper.data(forKey: Const.Keychain.Key.email)
11+
12+
return data.flatMap { String(data: $0, encoding: .utf8) }
13+
}
14+
15+
set {
16+
guard let token = newValue,
17+
let data = token.data(using: .utf8) else {
18+
wrapper.removeValue(forKey: Const.Keychain.Key.email)
19+
return
20+
}
21+
22+
wrapper.set(data, forKey: Const.Keychain.Key.email)
23+
}
24+
25+
}
26+
27+
var userId: String? {
28+
get {
29+
let data = wrapper.data(forKey: Const.Keychain.Key.userId)
30+
31+
return data.flatMap { String(data: $0, encoding: .utf8) }
32+
}
33+
34+
set {
35+
guard let token = newValue,
36+
let data = token.data(using: .utf8) else {
37+
wrapper.removeValue(forKey: Const.Keychain.Key.userId)
38+
return
39+
}
40+
41+
wrapper.set(data, forKey: Const.Keychain.Key.userId)
42+
}
43+
}
44+
845
var authToken: String? {
946
get {
1047
let data = wrapper.data(forKey: Const.Keychain.Key.authToken)
48+
1149
return data.flatMap { String(data: $0, encoding: .utf8) }
1250
}
1351
set {
1452
guard let token = newValue,
1553
let data = token.data(using: .utf8) else {
16-
wrapper.removeValue(forKey: Const.Keychain.Key.authToken)
17-
return
18-
}
54+
wrapper.removeValue(forKey: Const.Keychain.Key.authToken)
55+
return
56+
}
57+
1958
wrapper.set(data, forKey: Const.Keychain.Key.authToken)
2059
}
2160
}
@@ -69,14 +108,14 @@ class KeychainWrapper {
69108

70109
return status == noErr ? result as? Data : nil
71110
}
72-
111+
73112
@discardableResult
74113
func removeValue(forKey key: String) -> Bool {
75114
let keychainQueryDictionary: [String: Any] = setupKeychainQueryDictionary(forKey: key)
76-
115+
77116
// Delete
78117
let status: OSStatus = SecItemDelete(keychainQueryDictionary as CFDictionary)
79-
118+
80119
if status == errSecSuccess {
81120
return true
82121
} else {
@@ -98,7 +137,7 @@ class KeychainWrapper {
98137
return false
99138
}
100139
}
101-
140+
102141

103142
private let serviceName: String
104143

@@ -120,14 +159,14 @@ class KeychainWrapper {
120159

121160
return keychainQueryDictionary
122161
}
123-
162+
124163
private func update(_ value: Data, forKey key: String) -> Bool {
125164
let keychainQueryDictionary: [String: Any] = setupKeychainQueryDictionary(forKey: key)
126165
let updateDictionary = [SecValueData: value]
127166

128167
// Update
129168
let status: OSStatus = SecItemUpdate(keychainQueryDictionary as CFDictionary, updateDictionary as CFDictionary)
130-
169+
131170
if status == errSecSuccess {
132171
return true
133172
} else {
@@ -150,3 +189,4 @@ class KeychainWrapper {
150189
private let SecMatchLimitOne = kSecMatchLimitOne
151190
private let SecReturnData: String = kSecReturnData as String
152191
}
192+

swift-sdk/Internal/LocalStorage.swift

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,17 @@ struct LocalStorage: LocalStorageProtocol {
1313

1414
var userId: String? {
1515
get {
16-
iterableUserDefaults.userId
16+
keychain.userId
1717
} set {
18-
iterableUserDefaults.userId = newValue
18+
keychain.userId = newValue
1919
}
2020
}
2121

2222
var email: String? {
2323
get {
24-
iterableUserDefaults.email
24+
keychain.email
2525
} set {
26-
iterableUserDefaults.email = newValue
26+
keychain.email = newValue
2727
}
2828
}
2929

@@ -85,19 +85,36 @@ struct LocalStorage: LocalStorageProtocol {
8585

8686
func upgrade() {
8787
ITBInfo()
88-
moveJwtFromUserDefaultsToKeychain()
88+
89+
/// moves `email`, `userId`, and `authToken` from `UserDefaults` to `IterableKeychain`
90+
moveAuthDataFromUserDefaultsToKeychain()
8991
}
9092

9193
// MARK: Private
9294

9395
private let iterableUserDefaults: IterableUserDefaults
9496
private let keychain: IterableKeychain
95-
96-
private func moveJwtFromUserDefaultsToKeychain() {
97+
98+
private func moveAuthDataFromUserDefaultsToKeychain() {
9799
if let userDefaultAuthToken = iterableUserDefaults.authToken, keychain.authToken == nil {
98100
keychain.authToken = userDefaultAuthToken
99101
iterableUserDefaults.authToken = nil
100-
ITBInfo("updated: keychain auth token")
102+
103+
ITBInfo("UPDATED: moved authToken from UserDefaults to IterableKeychain")
104+
}
105+
106+
if let userDefaultEmail = iterableUserDefaults.email, keychain.email == nil {
107+
keychain.email = userDefaultEmail
108+
iterableUserDefaults.email = nil
109+
110+
ITBInfo("UPDATED: moved email from UserDefaults to IterableKeychain")
111+
}
112+
113+
if let userDefaultUserId = iterableUserDefaults.userId, keychain.userId == nil {
114+
keychain.userId = userDefaultUserId
115+
iterableUserDefaults.userId = nil
116+
117+
ITBInfo("UPDATED: moved userId from UserDefaults to IterableKeychain")
101118
}
102119
}
103120
}

tests/unit-tests/LocalStorageTests.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,38 @@ class LocalStorageTests: XCTestCase {
3333
XCTAssertEqual(localStorage.email, email)
3434
}
3535

36+
func testAuthDataInKeychain() {
37+
let testUserDefaults = LocalStorageTests.getTestUserDefaults()
38+
let testKeychain = IterableKeychain.init(wrapper: KeychainWrapper.init(serviceName: "test-localstorage"))
39+
40+
var localStorage = LocalStorage(userDefaults: testUserDefaults,
41+
keychain: testKeychain)
42+
43+
let userId = "user-id"
44+
45+
localStorage.userId = userId
46+
47+
XCTAssertNil(testUserDefaults.string(forKey: Const.UserDefault.userIdKey))
48+
49+
XCTAssertEqual(testKeychain.userId, userId)
50+
51+
let email = "[email protected]"
52+
53+
localStorage.email = email
54+
55+
XCTAssertNil(testUserDefaults.string(forKey: Const.UserDefault.emailKey))
56+
57+
XCTAssertEqual(testKeychain.email, email)
58+
59+
let authToken = "token"
60+
61+
localStorage.authToken = authToken
62+
63+
XCTAssertNil(testUserDefaults.string(forKey: Const.UserDefault.authTokenKey))
64+
65+
XCTAssertEqual(testKeychain.authToken, authToken)
66+
}
67+
3668
func testDDLChecked() throws {
3769
var localStorage = LocalStorage(userDefaults: LocalStorageTests.getTestUserDefaults())
3870
localStorage.ddlChecked = true

0 commit comments

Comments
 (0)