Keychain secure data storage setup in iOS

TRUETECH is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Keychain secure data storage setup in iOS
Medium
from 1 business day to 3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Setting up Keychain for Secure Data Storage in iOS

After app update, the authorization token is not found — user sees login screen again. Or worse: the token is saved, but accessible to another app from the same vendor without restrictions. Both situations result from improperly configured Keychain.

Where Exactly It Breaks

Most common mistake: storing tokens via UserDefaults. Data goes into Library/Preferences/*.plist, which is included in iCloud backup and accessible via iTunes backup extraction tools like iBackup Viewer. This is not theoretical.

Second most common: using Keychain without explicit kSecAttrAccessible. Default value is kSecAttrAccessibleWhenUnlocked, which is reasonable, but many projects don't consider whether data needs access when screen is locked (for background tasks) or only when device is unlocked and only after first unlock after reboot. These are fundamentally different threat models.

Third: missing kSecAttrAccessGroup when working in App Group. If you have main app and widget or extension, and token is not shared explicitly, extension won't see Keychain entry, even though Bundle ID is from the same group.

Proper Configuration via Security Framework

Basic write pattern:

let query: [String: Any] = [
    kSecClass as String:            kSecClassGenericPassword,
    kSecAttrService as String:      "com.example.app.auth",
    kSecAttrAccount as String:      "access_token",
    kSecAttrAccessible as String:   kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
    kSecValueData as String:        tokenData,
    kSecAttrAccessGroup as String:  "TEAMID.com.example.shared"  // if App Group needed
]

kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly is the right choice for most tokens: accessible after first unlock post-reboot, not synced to iCloud, not transferred to other devices. If you need synchronization between user's devices (e.g., notes password), then kSecAttrAccessibleWhenUnlocked with kSecAttrSynchronizable: kCFBooleanTrue. But for auth tokens, iCloud Keychain sync is undesirable — compromise of one device compromises all.

For read with update (upsert), first try SecItemUpdate, on errSecItemNotFoundSecItemAdd. Don't do SecItemDelete + SecItemAdd — creates race condition in multithreaded environment.

Biometric Protection via LocalAuthentication

If data needs biometric protection before access (encryption keys, private keys):

let access = SecAccessControlCreateWithFlags(
    nil,
    kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
    .biometryCurrentSet,  // .userPresence for passcode fallback
    nil
)!

Flag .biometryCurrentSet invalidates the record when biometry changes (new fingerprint, switch to Face ID) — intentional behavior for high-secret data. For less critical .biometryAny preserves access after new fingerprints are added.

Wrapper and Testability

Direct SecItemAdd calls in production code make unit-tests impossible without real Keychain. Wrap in protocol:

protocol KeychainService {
    func save(_ data: Data, for key: String) throws
    func load(for key: String) throws -> Data
    func delete(for key: String) throws
}

In tests, substitute InMemoryKeychainService. In production — implementation via Security framework. Standard approach in Clean Architecture for iOS.

Process

Audit current code — find UserDefaults, NSKeyedArchiver, plaintext in files. Next, design KeychainService for specific stored data set, implement with correct kSecAttrAccessible, configure App Group if extension sharing needed, cover with unit-tests via mock. Separately — test behavior on biometry change and app update.

Timeline: 1–3 days. Simple UserDefaults to Keychain swap for one data type — closer to one day. Full audit + refactor + App Group + biometry — up to three.