Search code examples
iosswiftkeychainswift5

Problem updating and deleting keychain in swift5


I have a problem updating and deleting keychain.

public func clearKeychain(username: String) throws -> Any?{
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: username
    ]
    let status = SecItemDelete(query as CFDictionary)

    if status != errSecSuccess {
        throw KeychainError.unhandledError(status: status)
    }
    print("Clear Keychain")
    return status
}

public func updateKeychain(username: String, password: String) throws -> Any?{
    let credentials = Credentials.init(username: username, password: password)
    let data = credentials.password.data(using: .utf8)!

    // store password as data and if you want to store username
    let query: [String: Any] = [kSecClass as String:  kSecClassGenericPassword,
                                kSecAttrAccount as String: username,
                                kSecValueData as String: data]
    let fields: [String: Any] = [
        kSecAttrAccount as String: username,
        kSecValueData as String: data
    ]
    let status = SecItemUpdate(query as CFDictionary, fields as CFDictionary)
    guard status == errSecSuccess else {
        throw KeychainError.unhandledError(status: status) }
    print("Updated Password")
    return status
}

Usage:

let _ = (try? keychain.clearKeychain(username: "KeychainUser")) as Any?
let _ = (try? keychain.updateKeychain(username: "KeychainUser", password: "123456789")) as Any?

Can't delete or update keychain. I have no problem creating and getting the value of the keychain, but I have a problem when updating or deleting. No error is shown. And status returns nil.


Solution

  • To update & delete your item, you need to search particular type of data. So you don't require to pass data in query. Just update your query as follow will fix issue on updating data.

    let query: [String: Any] = [kSecClass as String:  kSecClassGenericPassword]
    

    By default, keychain services deletes all keychain items that match the search parameters. If you want to delete a specific item that you already have a reference or persistent reference to, add that to the search dictionary as the value for the kSecMatchItemList key. In this way, you limit the deletion to only the specified item.