Example Code for Using Swift to Save and Query iOS Keychain
I wrote a couple of small utility functions for using the iOS Keychain with Swift. This has two very basic functions: to save a string to the Keychain, and to load that string back later. Iโll update this post if I need to update this utility service to handle deletion, updating, and so on.
Update: the best place to find the most up to date code is in the Locksmith repository.
KeychainService
import UIKit
import Security
// Identifiers
let serviceIdentifier = "MySerivice"
let userAccount = "authenticatedUser"
let accessGroup = "MySerivice"
// Arguments for the keychain queries
let kSecClassValue = kSecClass.takeRetainedValue() as NSString
let kSecAttrAccountValue = kSecAttrAccount.takeRetainedValue() as NSString
let kSecValueDataValue = kSecValueData.takeRetainedValue() as NSString
let kSecClassGenericPasswordValue = kSecClassGenericPassword.takeRetainedValue() as NSString
let kSecAttrServiceValue = kSecAttrService.takeRetainedValue() as NSString
let kSecMatchLimitValue = kSecMatchLimit.takeRetainedValue() as NSString
let kSecReturnDataValue = kSecReturnData.takeRetainedValue() as NSString
let kSecMatchLimitOneValue = kSecMatchLimitOne.takeRetainedValue() as NSString
class KeychainService: NSObject {
/**
* Exposed methods to perform queries.
* Note: feel free to play around with the arguments
* for these if you want to be able to customise the
* service identifier, user accounts, access groups, etc.
*/
public class func saveToken(token: NSString) {
self.save(serviceIdentifier, data: token)
}
public class func loadToken() -> NSString? {
var token = self.load(serviceIdentifier)
return token
}
/**
* Internal methods for querying the keychain.
*/
private class func save(service: NSString, data: NSString) {
var dataFromString: NSData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
// Instantiate a new default keychain query
var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, userAccount, dataFromString], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecValueDataValue])
// Delete any existing items
SecItemDelete(keychainQuery as CFDictionaryRef)
// Add the new keychain item
var status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil)
}
private class func load(service: NSString) -> NSString? {
// Instantiate a new default keychain query
// Tell the query to return a result
// Limit our results to one item
var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, userAccount, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue])
var dataTypeRef :Unmanaged<AnyObject>?
// Search for the keychain items
let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef)
let opaque = dataTypeRef?.toOpaque()
var contentsOfKeychain: NSString?
if let op = opaque? {
let retrievedData = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue()
// Convert the data retrieved from the keychain into a string
contentsOfKeychain = NSString(data: retrievedData, encoding: NSUTF8StringEncoding)
} else {
println("Nothing was retrieved from the keychain. Status code \(status)")
}
return contentsOfKeychain
}
}
Usage
It can then be used like this:
KeychainService.saveToken("token")
KeychainService.loadToken()
Updates
Thanks to rshelby, Iโve updated this code to work on later versions of the beta. Let me know on Twitter if it doesnโt work for you.
Xcode 6.1: @godzirra let me know on Twitter that doing let kSecClassValue = kSecClass.takeRetainedValue() as NSString
no longer works on Seed 2. Instead, you need to do let kSecClassValue = NSString(format: kSecClass)
. This applies to all of the arguments we provide to the keychain queries listed at the top of the snippet.
๐ Vanilla โ hide icons from your Mac menu bar for free
๐ Rocket โ super-fast emoji shortcuts everywhere on Macโฆ :clap: โ ๐
โณ Horo โ the best free timer app for Mac
๐ FastFolderFinder โ a lightning-fast launchbar app for folders and apps
๐ Kubernetes โ my book on Kubernetes for web app developers
๐ Emoji Bullet List โ easily emojify your bullet point lists (like this one!)
Jump on my email list to get sent the stuff thatโs too raunchy for the blog.
(Seriously though, itโs an occasional update on apps Iโve built and posts Iโve written recently.)