Swiftpack.co - spydercapriani/KeychainWrapper as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
See all packages published by spydercapriani.
spydercapriani/KeychainWrapper 1.2.0
Wrapper for Keychain
⭐️ 0
🕓 3 weeks ago
iOS macOS
.package(url: "https://github.com/spydercapriani/KeychainWrapper.git", from: "1.2.0")

KeychainWrapper

A library of wrappers / utilities for interacting with the Keychain.

Property Wrappers

SecureCredentials

Wrapper for generic password item in the keychain.

@SecureCredentials(
    label: "GitHub Token",              // Optional
    service: "github.token",            // Required
    account: "user@github.com"          // Optional
)
var gitHubPassword: String?

InternetCredentials

Wrapper for Internet password items in the keychain.

@InternetCredentials(
    label: "GitHub Token",                          // Optional
    server: URL(string: "https://www.github.com",   // Required
    account: "user@github.com"                      // Optional
)
var gitHubPassword: String?

SecureItem

Wrapper for codable items in the keychain.

@SecureItem(
    name: "Keychain Item Name"
)
var item: Codable?

** Advanced Tips ** To update account for wrappers, use the projectedValue like so:

$gitHub.account = "newAccount" // Updates the account field for the keychain item.

Keychain

Perform CRUD operation with the keychain via KeychainQuery's.

KeychainQueryable

public protocol KeychainQueryable {
    var attributes: KeychainAttributes { get }
    var options: KeychainOptions { get }
}

By conforming to this protocol, you can get all CRUD options for free.

// MARK: - CRUD Keychain Actions
public extension KeychainQueryable {
    
    var item: KeychainItem {
        get throws {
            try Keychain.search(for: attributes, with: options)
        }
    }
    
    func update(_ attributes: KeychainAttribute...) throws {
        let uniqueAttributes = KeychainAttributes(attributes)
        try Keychain.modify(uniqueAttributes, for: self)
    }
    
    func delete() throws {
        try Keychain.remove(self)
    }
}
  • Attributes are the necessary lookup attributes for the object.
  • Options are the set of search options necesary for lookup.

Pre-defined KeychainOptions

    static var matchFirst: Set<KeychainOption> {
        [
            .returnData(true),
            .returnAttributes(true),
            .matchLimit(.first)
        ]
    }
    
    static var matchAll: Set<KeychainOption> {
        [
            .returnData(true),
            .returnAttributes(true),
            .matchLimit(.all)
        ]
    }

Create / Update

Create items in the keychain.

NOTE: Update function creates the item if it doesn't exist.

let query: KeychainQuery = [
    kSecClass.string: kSecClassGenericPassword,
    kSecAttrLabel.string: "Example Label for Keychain Item",
    kSecAttrService.string: "Name of Service"
]

let attributes: KeychainAttributes = [
    kSecAttrAccount.string: "Username",
    kSecValueData.string: Data("Password".utf8)
]

try Keychain.update(attributes, using: query)

Read

Read items in the keychain.

let query: KeychainQuery = [
    kSecClass.string: kSecClassGenericPassword,
    kSecAttrLabel.string: "Example Label for Keychain Item",
    kSecAttrService.string: "Name of Service"
]

let searchOptions: KeychainOptions = [
    kSecReturnAttributes.string: true,
    kSecReturnData.string: true,
    kSecMatchLimit.string: kSecMatchLimitOne
]

let item = try Keychain.read(query, options: search)        // Returns a KeychainItem (i.e. [String: Any])
let account = item[kSecAttrAccount.string] as! String       // You'll be converting  
let passwordData = item[kSecValueData.string] as! Data

Delete

Delete items in the keychain.

let query: KeychainQuery = [
    kSecClass.string: kSecClassGenericPassword,
    kSecAttrLabel.string: "Example Label for Keychain Item",
    kSecAttrService.string: "Name of Service"
]

try Keychain.delete(query)

Advanced Tips / Notes

Be wary of using [kSecClass: kSecClassInternetPassword] when reading/creating entries in the keychain for this type cannot easily be read by apps outside of the one through which it was created. It is considered better practice to use kSecClassGenericPassword when creating entries which are intended to be shared between tools / apps as access can be granted by the user for these entries so long as they are not associated with the iCloud Keychain.

Recommend adding any undefined Keychain attributes in the KeychainAttribute namespace to make utilizing the Keychain functions easier.

Links

GitHub

link
Stars: 0
Last commit: 3 weeks ago
jonrohan Something's broken? Yell at me @ptrpavlik. Praise and feedback (and money) is also welcome.

Dependencies

Related Packages

Release Notes

SecureItem
3 weeks ago

Adds SecureItem which supports writing Coddle objects into the Keychain.

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics