Skip to content

Commit

Permalink
Moved accessGroup to the method level
Browse files Browse the repository at this point in the history
  • Loading branch information
mohssenfathi committed May 23, 2024
1 parent cd957c5 commit 6c5ad50
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 36 deletions.
62 changes: 37 additions & 25 deletions Sources/UberCore/Authentication/Tokens/KeychainUtility.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,42 +33,53 @@ 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<V: Encodable>(_ value: V, for key: String) -> Bool
func save<V: Encodable>(_ 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<V: Decodable>(key: String) -> V?
func get<V: Decodable>(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<V: Encodable>(_ value: V, for key: String) -> Bool {
save(value, for: key, accessGroup: nil)
}

func get<V: Decodable>(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 {

// 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

Expand All @@ -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<V: Encodable>(_ value: V, for key: String) -> Bool {
public func save<V: Encodable>(_ 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

Expand All @@ -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<V: Decodable>(key: String) -> V? {
public func get<V: Decodable>(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

Expand Down Expand Up @@ -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)

Expand All @@ -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
}

Expand Down
24 changes: 13 additions & 11 deletions Sources/UberCore/Authentication/Tokens/TokenManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -133,9 +140,4 @@ public final class TokenManager: TokenManaging {
}
}
}

private func updateAccessGroup(_ accessGroup: String?) {
guard let accessGroup else { return }
keychainUtility.setAccessGroup(accessGroup)
}
}

0 comments on commit 6c5ad50

Please sign in to comment.