Keychain Basics
Store small secrets (tokens, passwords) securely using Keychain APIs with proper access control.
Store a Secret (Add)
Use SecItemAdd with a dictionary describing the item.
Syntax:
SecItemAdd(attrs as CFDictionary, nil)- class
kSecClassGenericPassword - account/service keys.
Example
KeychainAdd.swift
ContentView.swift
App.swift
import Security
func saveToken(_ token: String) {
let data = token.data(using: .utf8)!
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: "com.example.auth",
kSecAttrAccount as String: "session",
kSecValueData as String: data,
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock
]
SecItemDelete(query as CFDictionary) // replace if exists
let status = SecItemAdd(query as CFDictionary, nil)
assert(status == errSecSuccess)
}
This example writes a token as a generic password, replacing any existing value for the same service/account.
Read a Secret (Query)
Use SecItemCopyMatching with kSecReturnData to get the stored bytes.
Syntax: SecItemCopyMatching(query as CFDictionary, &item)
Example
KeychainGet.swift
ContentView.swift
App.swift
import Security
func loadToken() -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: "com.example.auth",
kSecAttrAccount as String: "session",
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
guard status == errSecSuccess, let data = item as? Data else { return nil }
return String(data: data, encoding: .utf8)
}
This example reads the previously saved token by matching on service/account and returning the data.
Update or Delete
Update with SecItemUpdate passing an attributes-to-update dictionary; delete with SecItemDelete.
Syntax:
SecItemUpdate(query, updates)SecItemDelete(query)
Example
KeychainUpdate.swift
ContentView.swift
App.swift
import Security
func deleteToken() {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: "com.example.auth",
kSecAttrAccount as String: "session",
]
SecItemDelete(query as CFDictionary)
}
Leave a Reply