Storing an auth token in UserDefaults is one of the most common iOS security mistakes, and it is easy to make because UserDefaults is so convenient. The problem is that UserDefaults is not secure storage: it writes to a plain property list in your app's container, readable on a compromised or backed-up device. The Keychain exists for exactly this, encrypted, system-managed storage for small secrets. Here is why a token belongs in the Keychain, never in UserDefaults, and how to use each correctly.
Short answer
On iOS, store tokens, passwords, and other secrets in the Keychain, not in UserDefaults. Per Apple's Keychain documentation, the Keychain is encrypted, system-managed secure storage designed for small secrets, with access controls and hardware-backed key protection. UserDefaults, by contrast, stores values in a plain, unencrypted property list inside your app container, so anything there can be read from a backup or a compromised device. So UserDefaults is for non-sensitive preferences like settings and flags, while the Keychain is for anything that must stay confidential. Putting a token in UserDefaults is a storage vulnerability; moving it to the Keychain is the fix.
What you should know
- UserDefaults is not secure: it stores values in plain, unencrypted form.
- The Keychain is encrypted: system-managed storage for small secrets.
- Tokens belong in the Keychain: along with passwords and keys.
- UserDefaults is for preferences: non-sensitive settings and flags only.
- Keychain has access controls: choose an appropriate accessibility level.
Why is UserDefaults wrong for tokens?
Because it was never meant to be secure, and it is not. UserDefaults persists its data to a property list file in your app's container, stored in plain text, so any value you put there, including an auth token or an API key, is readable by anyone who can access the app's files. That includes someone inspecting a device backup, or an attacker on a jailbroken device browsing the container. There is no encryption and no access control on UserDefaults; it is a convenience store for small, non-sensitive values like a theme preference or an onboarding flag. So a token in UserDefaults is effectively stored in the clear, which is exactly the kind of insecure storage that turns a lost or compromised device into an account compromise.
Why is the Keychain the right place?
Because it is purpose-built secure storage for secrets. The Keychain encrypts the items you store, manages the keys for you with hardware backing on supported devices, and gates access with accessibility attributes that control when an item can be read, for example only while the device is in use and not locked. It is designed for small, sensitive values, exactly the size of a token, password, or key, and it persists across app launches. You also control whether items are restricted to the current device and excluded from backups. So the Keychain gives a token the encryption, access control, and key management that UserDefaults entirely lacks, which is why it is the standard place to keep anything confidential on iOS.
Keychain versus UserDefaults
The choice comes down to whether the value is sensitive. The table contrasts them.
| Aspect | Keychain | UserDefaults |
|---|---|---|
| Encryption | Yes, encrypted and key-managed | No, plain property list |
| Intended data | Small secrets: tokens, passwords, keys | Non-sensitive preferences and settings |
| Access control | Accessibility attributes per item | None |
| Backup and device scope | Configurable, can be device-only | Stored and backed up in the clear |
| Right for an auth token | Yes | No |
The takeaway is direct: a token, credential, or key goes in the Keychain, and UserDefaults is reserved for data you would not mind anyone reading. Choosing UserDefaults for a secret is the mistake; the Keychain is the correct default for confidential values.
What to watch out for
The first trap is reaching for UserDefaults because it is one line of code, when the value is a secret that belongs in the Keychain. The second is using an overly permissive Keychain accessibility level, so prefer one that requires the device to be in use rather than locked, and use a device-only option for items that should not move to a new device via backup. The third is storing a large or non-secret blob in the Keychain, which is the wrong tool for that. A pre-submission scan such as PTKD.com (https://ptkd.com) reads the compiled IPA against OWASP MASVS and flags sensitive data stored insecurely, such as a token in UserDefaults or a plist, so you can confirm secrets actually go to the Keychain before you ship. Moving the value to the Keychain is the fix it points you to.
What to take away
- Store tokens, passwords, and keys in the Keychain, which is encrypted, access-controlled, system-managed secure storage.
- Never store secrets in UserDefaults, which writes plain, unencrypted values readable from a backup or a compromised device.
- Use UserDefaults only for non-sensitive preferences, and choose an appropriate Keychain accessibility level, device-only where suitable.
- Use a pre-submission scan such as PTKD.com to catch any secret left in UserDefaults or a plist, then move it to the Keychain.


