fix: remove Keychain accessGroup — fixes auth reset and health data
- 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) <noreply@anthropic.com>
This commit is contained in:
@@ -39,11 +39,12 @@ struct PulseApp: App {
|
|||||||
.environmentObject(authManager)
|
.environmentObject(authManager)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
APIService.shared.authManager = authManager
|
APIService.shared.authManager = authManager
|
||||||
// Migrate: set health API key in Keychain if not yet
|
// Ensure health credentials are in Keychain
|
||||||
if authManager.healthApiKey.isEmpty {
|
if KeychainService.load(key: KeychainService.healthApiKeyKey) == nil {
|
||||||
authManager.setHealthApiKey("health-cosmo-2026")
|
KeychainService.save(key: KeychainService.healthApiKeyKey, value: "health-cosmo-2026")
|
||||||
HealthAPIService.configureCredentials(email: "daniilklimov25@gmail.com", password: "cosmo-health-2026")
|
HealthAPIService.configureCredentials(email: "daniilklimov25@gmail.com", password: "cosmo-health-2026")
|
||||||
}
|
}
|
||||||
|
authManager.healthApiKey = KeychainService.load(key: KeychainService.healthApiKeyKey) ?? ""
|
||||||
Self.scheduleHealthSync()
|
Self.scheduleHealthSync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,13 @@ import Security
|
|||||||
|
|
||||||
enum KeychainService {
|
enum KeychainService {
|
||||||
static let service = "com.daniil.pulsehealth"
|
static let service = "com.daniil.pulsehealth"
|
||||||
static let accessGroup = "V9AG8JTFLC.com.daniil.pulsehealth.shared"
|
|
||||||
|
|
||||||
static func save(key: String, value: String) {
|
static func save(key: String, value: String) {
|
||||||
guard let data = value.data(using: .utf8) else { return }
|
guard let data = value.data(using: .utf8) else { return }
|
||||||
let query: [String: Any] = [
|
let query: [String: Any] = [
|
||||||
kSecClass as String: kSecClassGenericPassword,
|
kSecClass as String: kSecClassGenericPassword,
|
||||||
kSecAttrService as String: service,
|
kSecAttrService as String: service,
|
||||||
kSecAttrAccount as String: key,
|
kSecAttrAccount as String: key
|
||||||
kSecAttrAccessGroup as String: accessGroup
|
|
||||||
]
|
]
|
||||||
SecItemDelete(query as CFDictionary)
|
SecItemDelete(query as CFDictionary)
|
||||||
var add = query
|
var add = query
|
||||||
@@ -25,7 +23,6 @@ enum KeychainService {
|
|||||||
kSecClass as String: kSecClassGenericPassword,
|
kSecClass as String: kSecClassGenericPassword,
|
||||||
kSecAttrService as String: service,
|
kSecAttrService as String: service,
|
||||||
kSecAttrAccount as String: key,
|
kSecAttrAccount as String: key,
|
||||||
kSecAttrAccessGroup as String: accessGroup,
|
|
||||||
kSecReturnData as String: true,
|
kSecReturnData as String: true,
|
||||||
kSecMatchLimit as String: kSecMatchLimitOne
|
kSecMatchLimit as String: kSecMatchLimitOne
|
||||||
]
|
]
|
||||||
@@ -39,8 +36,7 @@ enum KeychainService {
|
|||||||
let query: [String: Any] = [
|
let query: [String: Any] = [
|
||||||
kSecClass as String: kSecClassGenericPassword,
|
kSecClass as String: kSecClassGenericPassword,
|
||||||
kSecAttrService as String: service,
|
kSecAttrService as String: service,
|
||||||
kSecAttrAccount as String: key,
|
kSecAttrAccount as String: key
|
||||||
kSecAttrAccessGroup as String: accessGroup
|
|
||||||
]
|
]
|
||||||
SecItemDelete(query as CFDictionary)
|
SecItemDelete(query as CFDictionary)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,13 @@ import Security
|
|||||||
|
|
||||||
enum KeychainService {
|
enum KeychainService {
|
||||||
static let service = "com.daniil.pulsehealth"
|
static let service = "com.daniil.pulsehealth"
|
||||||
static let accessGroup = "V9AG8JTFLC.com.daniil.pulsehealth.shared"
|
|
||||||
|
|
||||||
static func save(key: String, value: String) {
|
static func save(key: String, value: String) {
|
||||||
guard let data = value.data(using: .utf8) else { return }
|
guard let data = value.data(using: .utf8) else { return }
|
||||||
let query: [String: Any] = [
|
let query: [String: Any] = [
|
||||||
kSecClass as String: kSecClassGenericPassword,
|
kSecClass as String: kSecClassGenericPassword,
|
||||||
kSecAttrService as String: service,
|
kSecAttrService as String: service,
|
||||||
kSecAttrAccount as String: key,
|
kSecAttrAccount as String: key
|
||||||
kSecAttrAccessGroup as String: accessGroup
|
|
||||||
]
|
]
|
||||||
SecItemDelete(query as CFDictionary)
|
SecItemDelete(query as CFDictionary)
|
||||||
var add = query
|
var add = query
|
||||||
@@ -25,7 +23,6 @@ enum KeychainService {
|
|||||||
kSecClass as String: kSecClassGenericPassword,
|
kSecClass as String: kSecClassGenericPassword,
|
||||||
kSecAttrService as String: service,
|
kSecAttrService as String: service,
|
||||||
kSecAttrAccount as String: key,
|
kSecAttrAccount as String: key,
|
||||||
kSecAttrAccessGroup as String: accessGroup,
|
|
||||||
kSecReturnData as String: true,
|
kSecReturnData as String: true,
|
||||||
kSecMatchLimit as String: kSecMatchLimitOne
|
kSecMatchLimit as String: kSecMatchLimitOne
|
||||||
]
|
]
|
||||||
@@ -39,8 +36,7 @@ enum KeychainService {
|
|||||||
let query: [String: Any] = [
|
let query: [String: Any] = [
|
||||||
kSecClass as String: kSecClassGenericPassword,
|
kSecClass as String: kSecClassGenericPassword,
|
||||||
kSecAttrService as String: service,
|
kSecAttrService as String: service,
|
||||||
kSecAttrAccount as String: key,
|
kSecAttrAccount as String: key
|
||||||
kSecAttrAccessGroup as String: accessGroup
|
|
||||||
]
|
]
|
||||||
SecItemDelete(query as CFDictionary)
|
SecItemDelete(query as CFDictionary)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user