Skip to content

Commit 7523001

Browse files
yaroluchkoharsh62
authored andcommitted
Addressing review comments: documentation, no more credentials valid check, only delete items if absolutely necessary
1 parent 1a3c717 commit 7523001

File tree

8 files changed

+49
-115
lines changed

8 files changed

+49
-115
lines changed

Amplify/Categories/Auth/Models/AccessGroup.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,43 @@
77

88
import Foundation
99

10+
/// A structure representing an access group for managing keychain items.
1011
public struct AccessGroup {
12+
/// The name of the access group.
1113
public let name: String?
14+
15+
/// A flag indicating whether to migrate keychain items.
1216
public let migrateKeychainItems: Bool
1317

18+
/**
19+
Initializes an `AccessGroup` with the specified name and migration option.
20+
21+
- Parameter name: The name of the access group.
22+
- Parameter migrateKeychainItemsOfUserSession: A flag indicating whether to migrate keychain items. Defaults to `false`.
23+
*/
1424
public init(name: String, migrateKeychainItemsOfUserSession: Bool = false) {
1525
self.init(name: name, migrateKeychainItems: migrateKeychainItemsOfUserSession)
1626
}
1727

28+
/**
29+
Creates an `AccessGroup` instance with no specified name.
30+
31+
- Parameter migrateKeychainItemsOfUserSession: A flag indicating whether to migrate keychain items.
32+
- Returns: An `AccessGroup` instance with the migration option set.
33+
*/
1834
public static func none(migrateKeychainItemsOfUserSession: Bool) -> AccessGroup {
1935
return .init(migrateKeychainItems: migrateKeychainItemsOfUserSession)
2036
}
2137

38+
/**
39+
A static property representing an `AccessGroup` with no name and no migration.
40+
41+
- Returns: An `AccessGroup` instance with no name and the migration option set to `false`.
42+
*/
2243
public static var none: AccessGroup {
2344
return .none(migrateKeychainItemsOfUserSession: false)
2445
}
25-
46+
2647
private init(name: String? = nil, migrateKeychainItems: Bool) {
2748
self.name = name
2849
self.migrateKeychainItems = migrateKeychainItems

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/CredentialStorage/AWSCognitoAuthCredentialStore.swift

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ struct AWSCognitoAuthCredentialStore {
2626
private var isKeychainConfiguredKey: String {
2727
"\(userDefaultsNameSpace).isKeychainConfigured"
2828
}
29+
/// This UserDefaults Key is use to retrieve the stored access group to determine
30+
/// which access group the migration should happen from
31+
/// If none is found, the unshared service is used for migration and all items
32+
/// under that service are queried
2933
private var accessGroupKey: String {
3034
"\(userDefaultsNameSpace).accessGroup"
3135
}
@@ -48,11 +52,14 @@ struct AWSCognitoAuthCredentialStore {
4852
self.keychain = KeychainStore(service: service)
4953
}
5054

55+
let oldAccessGroup = retrieveStoredAccessGroup()
5156
if migrateKeychainItemsOfUserSession {
5257
try? migrateKeychainItemsToAccessGroup()
58+
} else if oldAccessGroup == nil && oldAccessGroup != accessGroup{
59+
try? KeychainStore(service: service)._removeAll()
5360
}
5461

55-
try? saveStoredAccessGroup()
62+
saveStoredAccessGroup()
5663

5764
if !userDefaults.bool(forKey: isKeychainConfiguredKey) {
5865
try? clearAllCredentials()
@@ -202,11 +209,11 @@ extension AWSCognitoAuthCredentialStore: AmplifyAuthCredentialStoreBehavior {
202209
try keychain._removeAll()
203210
}
204211

205-
private func retrieveStoredAccessGroup() throws -> String? {
212+
private func retrieveStoredAccessGroup() -> String? {
206213
return userDefaults.string(forKey: accessGroupKey)
207214
}
208215

209-
private func saveStoredAccessGroup() throws {
216+
private func saveStoredAccessGroup() {
210217
if let accessGroup {
211218
userDefaults.set(accessGroup, forKey: accessGroupKey)
212219
} else {
@@ -215,33 +222,10 @@ extension AWSCognitoAuthCredentialStore: AmplifyAuthCredentialStoreBehavior {
215222
}
216223

217224
private func migrateKeychainItemsToAccessGroup() throws {
218-
let oldAccessGroup = try? retrieveStoredAccessGroup()
219-
let oldKeychain: KeychainStoreBehavior
225+
let oldAccessGroup = retrieveStoredAccessGroup()
220226

221227
if oldAccessGroup == accessGroup {
222-
log.verbose("[AWSCognitoAuthCredentialStore] Stored access group is the same as current access group, aborting migration")
223-
return
224-
}
225-
226-
if let oldAccessGroup {
227-
oldKeychain = KeychainStore(service: sharedService, accessGroup: oldAccessGroup)
228-
} else {
229-
oldKeychain = KeychainStore(service: service)
230-
}
231-
232-
let authCredentialStoreKey = generateSessionKey(for: authConfiguration)
233-
let authCredentialData: Data
234-
let awsCredential: AmplifyCredentials
235-
do {
236-
authCredentialData = try oldKeychain._getData(authCredentialStoreKey)
237-
awsCredential = try decode(data: authCredentialData)
238-
} catch {
239-
log.verbose("[AWSCognitoAuthCredentialStore] Could not retrieve previous credentials in keychain under old access group, nothing to migrate")
240-
return
241-
}
242-
243-
guard awsCredential.areValid() else {
244-
log.verbose("[AWSCognitoAuthCredentialStore] Credentials found are not valid (expired) in old access group keychain, aborting migration")
228+
log.info("[AWSCognitoAuthCredentialStore] Stored access group is the same as current access group, aborting migration")
245229
return
246230
}
247231

@@ -281,10 +265,4 @@ private extension AWSCognitoAuthCredentialStore {
281265

282266
}
283267

284-
extension AWSCognitoAuthCredentialStore: DefaultLogger {
285-
public static var log: Logger {
286-
Amplify.Logging.logger(forNamespace: String(describing: self))
287-
}
288-
289-
public nonisolated var log: Logger { Self.log }
290-
}
268+
extension AWSCognitoAuthCredentialStore: DefaultLogger { }

AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AWSCognitoSecureStoragePreferences.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@
88
import Foundation
99
import Amplify
1010

11+
/// A struct to store preferences for how the plugin uses storage
1112
public struct AWSCognitoSecureStoragePreferences {
1213

1314
/// The access group that the keychain will use for auth items
1415
public let accessGroup: AccessGroup?
1516

17+
/// Creates an intstance of AWSCognitoSecureStoragePreferences
18+
/// - Parameters:
19+
/// - accessGroup: access group to be used
1620
public init(accessGroup: AccessGroup? = nil) {
1721
self.accessGroup = accessGroup
1822
}

AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ActionTests/CredentialStore/MockCredentialStoreBehavior.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@ class MockKeychainStoreBehavior: KeychainStoreBehavior {
1515
typealias VoidHandler = () -> Void
1616

1717
let data: String
18-
let allData: [(key: String, value: Data)]
1918
let removeAllHandler: VoidHandler?
2019
let mockKey: String = "mockKey"
2120

2221
init(data: String,
2322
removeAllHandler: VoidHandler? = nil) {
2423
self.data = data
2524
self.removeAllHandler = removeAllHandler
26-
self.allData = [(key: mockKey, value: Data(data.utf8))]
2725
}
2826

2927
func _getString(_ key: String) throws -> String {
@@ -45,7 +43,4 @@ class MockKeychainStoreBehavior: KeychainStoreBehavior {
4543
removeAllHandler?()
4644
}
4745

48-
func _getAll() throws -> [(key: String, value: Data)] {
49-
return allData
50-
}
5146
}

AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/Support/DefaultConfig.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -366,10 +366,6 @@ struct MockLegacyStore: KeychainStoreBehavior {
366366
func _removeAll() throws {
367367

368368
}
369-
370-
func _getAll() throws -> [(key: String, value: Data)] {
371-
return []
372-
}
373369

374370
}
375371

AmplifyPlugins/Core/AWSPluginsCore/Keychain/KeychainStore.swift

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ public protocol KeychainStoreBehavior {
5353
/// This System Programming Interface (SPI) may have breaking changes in future updates.
5454
func _removeAll() throws
5555

56-
@_spi(KeychainStore)
57-
/// Retrieves all key-value pairs in the keychain
58-
/// This System Programming Interface (SPI) may have breaking changes in future updates.
59-
func _getAll() throws -> [(key: String, value: Data)]
6056
}
6157

6258
public struct KeychainStore: KeychainStoreBehavior {
@@ -236,48 +232,6 @@ public struct KeychainStore: KeychainStoreBehavior {
236232
}
237233
log.verbose("[KeychainStore] Successfully removed all items from keychain")
238234
}
239-
240-
@_spi(KeychainStore)
241-
/// Retrieves all key-value pairs in the keychain
242-
/// This System Programming Interface (SPI) may have breaking changes in future updates.
243-
public func _getAll() throws -> [(key: String, value: Data)] {
244-
log.verbose("[KeychainStore] Starting to retrieve all items from keychain")
245-
var query = attributes.defaultGetQuery()
246-
query[Constants.MatchLimit] = Constants.MatchLimitAll
247-
query[Constants.ReturnData] = kCFBooleanTrue
248-
query[Constants.ReturnAttributes] = kCFBooleanTrue
249-
query[Constants.ReturnRef] = kCFBooleanTrue
250-
251-
var result: AnyObject?
252-
let status = SecItemCopyMatching(query as CFDictionary, &result)
253-
254-
switch status {
255-
case errSecSuccess:
256-
guard let items = result as? [[String: Any]] else {
257-
log.error("[KeychainStore] The keychain items retrieved are not the correct type")
258-
throw KeychainStoreError.unknown("The keychain items retrieved are not the correct type")
259-
}
260-
261-
var keyValuePairs = [(key: String, value: Data)]()
262-
for item in items {
263-
guard let key = item[Constants.AttributeAccount] as? String,
264-
let value = item[Constants.ValueData] as? Data else {
265-
log.error("[KeychainStore] Unable to retrieve key or value from keychain item")
266-
continue
267-
}
268-
keyValuePairs.append((key: key, value: value))
269-
}
270-
271-
log.verbose("[KeychainStore] Successfully retrieved \(keyValuePairs.count) items from keychain")
272-
return keyValuePairs
273-
case errSecItemNotFound:
274-
log.verbose("[KeychainStore] No items found in keychain")
275-
return []
276-
default:
277-
log.error("[KeychainStore] Error of status=\(status) occurred when attempting to retrieve all items from keychain")
278-
throw KeychainStoreError.securityError(status)
279-
}
280-
}
281235

282236
}
283237

AmplifyPlugins/Core/AWSPluginsCore/Keychain/KeychainStoreMigrator.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,21 @@ public struct KeychainStoreMigrator {
2020
public func migrate() throws {
2121
log.verbose("[KeychainStoreMigrator] Starting to migrate items")
2222

23+
// Check if there are any existing items under the new service and access group
24+
let existingItemsQuery = newAttributes.defaultGetQuery()
25+
let existingItemsStatus = SecItemCopyMatching(existingItemsQuery as CFDictionary, nil)
26+
27+
if existingItemsStatus == errSecSuccess {
28+
// Remove existing items to avoid duplicate item error
29+
try? KeychainStore(service: newAttributes.service, accessGroup: newAttributes.accessGroup)._removeAll()
30+
}
31+
2332
var updateQuery = oldAttributes.defaultGetQuery()
2433

2534
var updateAttributes = [String: Any]()
2635
updateAttributes[KeychainStore.Constants.AttributeService] = newAttributes.service
2736
updateAttributes[KeychainStore.Constants.AttributeAccessGroup] = newAttributes.accessGroup
2837

29-
// Remove any current items to avoid duplicate item error
30-
try? KeychainStore(service: newAttributes.service, accessGroup: newAttributes.accessGroup)._removeAll()
31-
3238
let updateStatus = SecItemUpdate(updateQuery as CFDictionary, updateAttributes as CFDictionary)
3339
switch updateStatus {
3440
case errSecSuccess:
@@ -47,10 +53,4 @@ public struct KeychainStoreMigrator {
4753
}
4854
}
4955

50-
extension KeychainStoreMigrator: DefaultLogger {
51-
public static var log: Logger {
52-
Amplify.Logging.logger(forNamespace: String(describing: self))
53-
}
54-
55-
public nonisolated var log: Logger { Self.log }
56-
}
56+
extension KeychainStoreMigrator: DefaultLogger { }

AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/Mocks/MockKeychainStore.swift

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,6 @@ class MockKeychainStore: KeychainStoreBehavior {
6161
stringValues.removeAll()
6262
dataValues.removeAll()
6363
}
64-
65-
func _getAll() throws -> [(key: String, value: Data)] {
66-
var allValues: [(key: String, value: Data)] = []
67-
68-
for (key, value) in dataValues {
69-
allValues.append((key: key, value: value))
70-
}
71-
72-
for (key, value) in stringValues {
73-
allValues.append((key: key, value: value.data(using: .utf8)!))
74-
}
75-
76-
return allValues
77-
}
7864

7965
func resetCounters() {
8066
dataForKeyCount = 0

0 commit comments

Comments
 (0)