Storing Password in System keychain (File-Based Keychain) for MFA Authorization Plugin

Hi everyone,

I’m currently developing an MFA authorization plugin for macOS and am looking to implement a passwordless feature. The goal is to store the user's password securely when they log into the system through the authorization plugin.

However, I’m facing an issue with using the system's login keychain (Data Protection Keychain), as it runs in the user context, which isn’t suitable for my case. Therefore, I need to store the password in a file-based keychain instead.

Does anyone have experience or code snippets for objective-c for securely storing passwords in a file-based keychain (outside of the login keychain) on macOS? Specifically, I'm looking for a solution that would work within the context of a system-level authorization plugin.

Any advice or sample code would be greatly appreciated!

Thanks in advance!

Answered by DTS Engineer in 815401022

There’s tonnes of SecItem sample code out there. To target the system keychain, use kSecUseKeychain for add operations and kSecMatchSearchList for query operations.

The SecItem API is hard to use correctly. The following posts have a bunch of hints and tips:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

There’s tonnes of SecItem sample code out there. To target the system keychain, use kSecUseKeychain for add operations and kSecMatchSearchList for query operations.

The SecItem API is hard to use correctly. The following posts have a bunch of hints and tips:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

So I have write this code

func systemKeychain() -> SecKeychain? {
    var searchListQ: CFArray? = nil
    let err = SecKeychainCopyDomainSearchList(.system, &searchListQ)
    guard err == errSecSuccess else {
        return nil
    }
    let searchList = searchListQ! as! [SecKeychain]
    return searchList.first
}

func storePasswordInSpecificKeychain(service: String, account: String, password: String) -> OSStatus {
    // Get a reference to the System Keychain
    guard let systemKeychainRef = systemKeychain() else {
            print("Error: Could not get a reference to the system keychain.")
            return errSecNoSuchKeychain
        }
    
    // Convert the password to Data
    guard let passwordData = password.data(using: .utf8) else {
        print("Failed to convert password to data.")
        return errSecParam
    }
    
    // Define the query to add the password
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrService as String: service,
        kSecAttrAccount as String: account,
        kSecValueData as String: passwordData,
        kSecUseKeychain as String: systemKeychainRef // Specify the System Keychain
    ]
    
    // Add the item to the System Keychain
    let status = SecItemAdd(query as CFDictionary, nil)
    
    // Handle the result
    if status == errSecSuccess {
        print("Password successfully added to the System Keychain.")
    } else if status == errSecDuplicateItem {
        print("Item already exists. Consider updating it instead.")
    } else {
        print("Failed to add password: \(SecCopyErrorMessageString(status,nil) ?? "Unknown error" as CFString)")
    }
    
    return status
}

but I am getting the error

Failed to add password: Write permissions error. Operation status: -61

how I can give resolve this

I resolved the issue. It turns out the app needed to be run as root. Thank you for your help!

Storing Password in System keychain (File-Based Keychain) for MFA Authorization Plugin
 
 
Q