diff --git a/Sources/UberCore/Authentication/Tokens/KeychainUtility.swift b/Sources/UberCore/Authentication/Tokens/KeychainUtility.swift index c40b0bc..c23e6f4 100644 --- a/Sources/UberCore/Authentication/Tokens/KeychainUtility.swift +++ b/Sources/UberCore/Authentication/Tokens/KeychainUtility.swift @@ -33,26 +33,40 @@ public protocol KeychainUtilityProtocol { /// - Parameters: /// - value: The object to save. Must conform to the Codable protocol. /// - key: A string value used to identify the saved object + /// - accessGroup: The accessGroup for which the operation should be performed /// - Returns: A boolean indicating whether or not the save operation was successful - func save(_ value: V, for key: String) -> Bool + func save(_ value: V, for key: String, accessGroup: String?) -> Bool /// Retrieves an object from the on device keychain using the supplied `key` /// /// - Parameters: /// - key: The identifier string used when saving the object + /// - accessGroup: The accessGroup for which the operation should be performed /// - Returns: If found, an optional type conforming to the Codable protocol - func get(key: String) -> V? + func get(key: String, accessGroup: String?) -> V? /// Removes the object from the on device keychain corresponding to the supplied `key` /// /// - Parameters: /// - key: The identifier string used when saving the object + /// - accessGroup: The accessGroup for which the operation should be performed /// - Returns: A boolean indicating whether or not the delete operation was successful - func delete(key: String) -> Bool + func delete(key: String, accessGroup: String?) -> Bool +} + +public extension KeychainUtilityProtocol { + + func save(_ value: V, for key: String) -> Bool { + save(value, for: key, accessGroup: nil) + } + + func get(key: String) -> V? { + get(key: key, accessGroup: nil) + } - /// Updates the accessGroup used for subsequent operations - /// - Parameter accessGroup: The new accessGroup - func setAccessGroup(_ accessGroup: String) + func delete(key: String) -> Bool { + delete(key: key, accessGroup: nil) + } } public final class KeychainUtility: KeychainUtilityProtocol { @@ -60,15 +74,12 @@ public final class KeychainUtility: KeychainUtilityProtocol { // MARK: Properties private let serviceName = "com.uber.uber-ios-sdk" - private var accessGroup: String private let encoder = JSONEncoder() private let decoder = JSONDecoder() // MARK: Initializers - public init(accessGroup: String = "") { - self.accessGroup = accessGroup - } + public init() {} // MARK: KeychainUtilityProtocol @@ -79,14 +90,15 @@ public final class KeychainUtility: KeychainUtilityProtocol { /// - Parameters: /// - value: The object to save. Must conform to the Codable protocol. /// - key: A string value used to identify the saved object + /// - accessGroup: The accessGroup for which the operation should be performed /// - Returns: A boolean indicating whether or not the save operation was successful - public func save(_ value: V, for key: String) -> Bool { + public func save(_ value: V, for key: String, accessGroup: String? = nil) -> Bool { guard let data = try? encoder.encode(value) else { return false } let valueData = NSData(data: data) - var attributes = attributes(for: key) + var attributes = attributes(for: key, accessGroup: accessGroup) attributes[Attribute.accessible] = kSecAttrAccessibleWhenUnlocked attributes[Attribute.valueData] = valueData @@ -111,10 +123,11 @@ public final class KeychainUtility: KeychainUtilityProtocol { /// /// - Parameters: /// - key: The identifier string used when saving the object + /// - accessGroup: The accessGroup for which the operation should be performed /// - Returns: If found, an optional type conforming to the Codable protocol - public func get(key: String) -> V? { + public func get(key: String, accessGroup: String? = nil) -> V? { - var attributes = attributes(for: key) + var attributes = attributes(for: key, accessGroup: accessGroup) attributes[Attribute.matchLimit] = kSecMatchLimitOne attributes[Attribute.returnData] = kCFBooleanTrue @@ -142,25 +155,23 @@ public final class KeychainUtility: KeychainUtilityProtocol { /// /// - Parameters: /// - key: The identifier string used when saving the object + /// - accessGroup: The accessGroup for which the operation should be performed /// - Returns: A boolean indicating whether or not the delete operation was successful - public func delete(key: String) -> Bool { + public func delete(key: String, accessGroup: String? = nil) -> Bool { SecItemDelete( - attributes(for: key) as CFDictionary + attributes(for: key, accessGroup: accessGroup) as CFDictionary ) == noErr } - /// Updates the accessGroup used for subsequent operations - /// - Parameter accessGroup: The new accessGroup - public func setAccessGroup(_ accessGroup: String) { - self.accessGroup = accessGroup - } - // MARK: Private /// Builds a base set of attributes used to perform a keychain storage operation - /// - Parameter key: The object identifier + /// + /// - Parameters: + /// - key: The object identifier + /// - accessGroup: An optional access group identifier /// - Returns: A dictionary containing the attributes - private func attributes(for key: String) -> [String: Any] { + private func attributes(for key: String, accessGroup: String?) -> [String: Any] { let identifier = key.data(using: .utf8) @@ -170,7 +181,8 @@ public final class KeychainUtility: KeychainUtilityProtocol { itemData[Attribute.service] = serviceName as AnyObject itemData[Attribute.class] = kSecClassGenericPassword - if !accessGroup.isEmpty { + if let accessGroup, + !accessGroup.isEmpty { itemData[Attribute.accessGroup] = accessGroup as AnyObject } diff --git a/Sources/UberCore/Authentication/Tokens/TokenManager.swift b/Sources/UberCore/Authentication/Tokens/TokenManager.swift index 835f0b3..c2b5408 100644 --- a/Sources/UberCore/Authentication/Tokens/TokenManager.swift +++ b/Sources/UberCore/Authentication/Tokens/TokenManager.swift @@ -87,8 +87,11 @@ public final class TokenManager: TokenManaging { public func saveToken(_ token: AccessToken, identifier: String = TokenManager.defaultAccessTokenIdentifier, accessGroup: String? = nil) -> Bool { - updateAccessGroup(accessGroup) - return keychainUtility.save(token, for: identifier) + keychainUtility.save( + token, + for: identifier, + accessGroup: accessGroup + ) } // MARK: Get @@ -99,8 +102,10 @@ public final class TokenManager: TokenManaging { /// - Returns: An optional Access Token if found public func getToken(identifier: String = TokenManager.defaultAccessTokenIdentifier, accessGroup: String? = nil) -> AccessToken? { - updateAccessGroup(accessGroup) - return keychainUtility.get(key: identifier) + keychainUtility.get( + key: identifier, + accessGroup: accessGroup + ) } // MARK: Delete @@ -113,8 +118,10 @@ public final class TokenManager: TokenManaging { public func deleteToken(identifier: String = TokenManager.defaultAccessTokenIdentifier, accessGroup: String? = nil) -> Bool { deleteCookies() - updateAccessGroup(accessGroup) - return keychainUtility.delete(key: identifier) + return keychainUtility.delete( + key: identifier, + accessGroup: accessGroup + ) } // MARK: Private Interface @@ -133,9 +140,4 @@ public final class TokenManager: TokenManaging { } } } - - private func updateAccessGroup(_ accessGroup: String?) { - guard let accessGroup else { return } - keychainUtility.setAccessGroup(accessGroup) - } }