Skip to content

Commit 3fedfda

Browse files
Fix Mac Catalyst reconnect race by updating keychain password in place instead of delete-then-add
1 parent c7635b2 commit 3fedfda

1 file changed

Lines changed: 21 additions & 5 deletions

File tree

LocalPackages/PIALibrary/Sources/PIALibrary/Util/Keychain.swift

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,33 @@ public class Keychain {
8282

8383
/// :nodoc:
8484
public func set(password: String, for username: String) throws {
85-
removePassword(for: username)
85+
guard let data = password.data(using: .utf8) else {
86+
throw KeychainError.add
87+
}
8688

8789
var query = [String: Any]()
8890
setScope(query: &query)
8991
query[kSecClass as String] = kSecClassGenericPassword
9092
query[kSecAttrAccount as String] = username
91-
query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
92-
query[kSecValueData as String] = password.data(using: .utf8)
9393

94-
let status = SecItemAdd(query as CFDictionary, nil)
95-
guard (status == errSecSuccess) else {
94+
let attributesToUpdate: [String: Any] = [
95+
kSecValueData as String: data,
96+
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock
97+
]
98+
let updateStatus = SecItemUpdate(query as CFDictionary, attributesToUpdate as CFDictionary)
99+
100+
switch updateStatus {
101+
case errSecSuccess:
102+
return
103+
case errSecItemNotFound:
104+
// No existing item — add a fresh one.
105+
query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
106+
query[kSecValueData as String] = data
107+
let addStatus = SecItemAdd(query as CFDictionary, nil)
108+
guard addStatus == errSecSuccess else {
109+
throw KeychainError.add
110+
}
111+
default:
96112
throw KeychainError.add
97113
}
98114
}

0 commit comments

Comments
 (0)