From 0c21a14cb9f0d15f291a566da3b365658650936d Mon Sep 17 00:00:00 2001 From: Daniil Klimov Date: Mon, 6 Apr 2026 14:29:52 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20remove=20Keychain=20accessGroup=20?= =?UTF-8?q?=E2=80=94=20fixes=20auth=20reset=20and=20health=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove kSecAttrAccessGroup from KeychainService (requires entitlement that keeps getting stripped by Xcode) - Basic Keychain works without accessGroup for the main app - Fix health credentials migration check — use KeychainService.load directly - Tokens now persist correctly between app launches Co-Authored-By: Claude Opus 4.6 (1M context) --- PulseHealth/App.swift | 7 ++++--- PulseHealth/Services/KeychainService.swift | 8 ++------ PulseWidget/KeychainService.swift | 8 ++------ 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/PulseHealth/App.swift b/PulseHealth/App.swift index 8555358..25060b9 100644 --- a/PulseHealth/App.swift +++ b/PulseHealth/App.swift @@ -39,11 +39,12 @@ struct PulseApp: App { .environmentObject(authManager) .onAppear { APIService.shared.authManager = authManager - // Migrate: set health API key in Keychain if not yet - if authManager.healthApiKey.isEmpty { - authManager.setHealthApiKey("health-cosmo-2026") + // Ensure health credentials are in Keychain + if KeychainService.load(key: KeychainService.healthApiKeyKey) == nil { + KeychainService.save(key: KeychainService.healthApiKeyKey, value: "health-cosmo-2026") HealthAPIService.configureCredentials(email: "daniilklimov25@gmail.com", password: "cosmo-health-2026") } + authManager.healthApiKey = KeychainService.load(key: KeychainService.healthApiKeyKey) ?? "" Self.scheduleHealthSync() } } diff --git a/PulseHealth/Services/KeychainService.swift b/PulseHealth/Services/KeychainService.swift index 434763f..782fa28 100644 --- a/PulseHealth/Services/KeychainService.swift +++ b/PulseHealth/Services/KeychainService.swift @@ -3,15 +3,13 @@ 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 + kSecAttrAccount as String: key ] SecItemDelete(query as CFDictionary) var add = query @@ -25,7 +23,6 @@ enum KeychainService { kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: key, - kSecAttrAccessGroup as String: accessGroup, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] @@ -39,8 +36,7 @@ enum KeychainService { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, - kSecAttrAccount as String: key, - kSecAttrAccessGroup as String: accessGroup + kSecAttrAccount as String: key ] SecItemDelete(query as CFDictionary) } diff --git a/PulseWidget/KeychainService.swift b/PulseWidget/KeychainService.swift index 434763f..782fa28 100644 --- a/PulseWidget/KeychainService.swift +++ b/PulseWidget/KeychainService.swift @@ -3,15 +3,13 @@ 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 + kSecAttrAccount as String: key ] SecItemDelete(query as CFDictionary) var add = query @@ -25,7 +23,6 @@ enum KeychainService { kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: key, - kSecAttrAccessGroup as String: accessGroup, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] @@ -39,8 +36,7 @@ enum KeychainService { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, - kSecAttrAccount as String: key, - kSecAttrAccessGroup as String: accessGroup + kSecAttrAccount as String: key ] SecItemDelete(query as CFDictionary) }