import Foundation import Security enum KeychainService { static let service = "com.daniil.pulsehealth" static let accessGroup = "V9AG8JTFLC.com.daniil.pulsehealth.shared" static func save(key: String, value: String) { guard let data = value.data(using: .utf8) else { return } let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: key, kSecAttrAccessGroup as String: accessGroup ] SecItemDelete(query as CFDictionary) var add = query add[kSecValueData as String] = data add[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock SecItemAdd(add as CFDictionary, nil) } static func load(key: String) -> String? { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: key, kSecAttrAccessGroup as String: accessGroup, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] var result: AnyObject? guard SecItemCopyMatching(query as CFDictionary, &result) == errSecSuccess, let data = result as? Data else { return nil } return String(data: data, encoding: .utf8) } static func delete(key: String) { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: key, kSecAttrAccessGroup as String: accessGroup ] SecItemDelete(query as CFDictionary) } // Keys static let tokenKey = "auth_token" static let refreshTokenKey = "auth_refresh_token" static let healthTokenKey = "health_jwt_token" static let healthApiKeyKey = "health_api_key" }