import Foundation import Security enum KeychainStore { private static let service = "uk.co.kasztelan.app.ios" private static let account = "api-token" static func save(token: String) throws { let data = Data(token.utf8) let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: account ] SecItemDelete(query as CFDictionary) var item = query item[kSecValueData as String] = data item[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly let status = SecItemAdd(item as CFDictionary, nil) guard status == errSecSuccess else { throw NSError(domain: NSOSStatusErrorDomain, code: Int(status)) } } static func load() -> String { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: account, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] var result: CFTypeRef? guard SecItemCopyMatching(query as CFDictionary, &result) == errSecSuccess, let data = result as? Data else { return "" } return String(data: data, encoding: .utf8) ?? "" } static func clear() { SecItemDelete([ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: account ] as CFDictionary) } }