import Foundation #if os(iOS) import Security #endif protocol TokenStore: AnyObject { var jwt: String? { get set } func clear() } final class DefaultTokenStore: TokenStore { private let key = "auth_jwt" private let defaults = UserDefaults.standard var jwt: String? { get { #if os(iOS) if let keychainValue = loadKeychainValue(for: key) { return keychainValue } #endif return defaults.string(forKey: key) } set { #if os(iOS) if let newValue { saveKeychainValue(newValue, for: key) } else { deleteKeychainValue(for: key) } #endif defaults.set(newValue, forKey: key) } } func clear() { #if os(iOS) deleteKeychainValue(for: key) #endif defaults.removeObject(forKey: key) } #if os(iOS) private var serviceName: String { "com.br.pedifoods.app.auth" } private func saveKeychainValue(_ value: String, for key: String) { guard let data = value.data(using: .utf8) else { return } let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: serviceName, kSecAttrAccount as String: key ] SecItemDelete(query as CFDictionary) let attributes: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: serviceName, kSecAttrAccount as String: key, kSecValueData as String: data ] SecItemAdd(attributes as CFDictionary, nil) } private func loadKeychainValue(for key: String) -> String? { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: serviceName, kSecAttrAccount as String: key, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] var result: AnyObject? let status = SecItemCopyMatching(query as CFDictionary, &result) guard status == errSecSuccess, let data = result as? Data, let value = String(data: data, encoding: .utf8) else { return nil } return value } private func deleteKeychainValue(for key: String) { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: serviceName, kSecAttrAccount as String: key ] SecItemDelete(query as CFDictionary) } #endif }