From TOF : Saving and loading private iOS app data

[Jeffrey Massung]
My iOS app goes through a login process to eventually be given an authentication token that can be used for a period of time (e.g. 24 hours) before it expires and a new one is needed.

What I’d like to do is save that token somewhere on the device that only my app has access to so that the user can quit, reload, and get access to it using FaceID/thumbprint and only have to re-authenticate if the token has expired.

I’m not finding any sandboxed storage location (or functionality) that only my app has access to. I suppose I could write directly to the drive and encrypt the data, but I’d prefer not to if there’s something already built-in for this use case.

[Greg O]
Typically you would store this type of info in the keychain.

NO. simple items should be stored in UserDefault.standard (a Plist)
Large amounts of data should be in a textfile or Sqlite Database in either /Documents or /Application Support

this is more like an access token/key
that should be in keychain shouldnt it ?

I truly haven’t kept up on where apple says

Is UserDefault readable by ANYTHING else ?
if so that might be undesirable for a secret key like this

No user default is not readable by anything else (or if it is, it is not easy) as this (and /Documents even) are inside the sandbox.

I would be that Keychain has a more global access on iOS, but I could be wrong there

Apple seems to suggest this is a good place to put such a thing

Computer users often have small secrets that they need to store securely. For example, most people manage numerous online accounts. Remembering a complex, unique password for each is impossible, but writing them down is both insecure and tedious. Users typically respond to this situation by recycling simple passwords across many accounts, which is also insecure.

NOW whether they also have recommendations about UserDefault.standard I dont know

This shouldnt according to the poster on TOF, be readable by other apps
UserDefault.standard seems like it may be

UsersDefault to the best of my knowledge is App specific and inside the Sandbox… While I believe that the keychain is System accessible and outside the sandbox…

User defaults just seems deliberately less secure - certainly doesnt require user authorization to access it which Keychain does
On macOS any other app could ask to read them and the system will permit it

  • edit - SOMETIMES (see below)
    Hence why you’d use keychain on the desktop

iOS I don’t know if the API’s isolate UserDefaults the same way
They might
~~ ~~
Which might mean on iOS either could work

so yeah they seem isolated from other apps meaning you could probably use either keychain or user defaults
one will be stored encrypted (keychain) - the other wont necessarily be stored encrypted

If I may.

The Keychain is an encrypted file and trying to read data from a different application requires keychain owner approval. If an app has access to a device file system, the keychain file is unsuable.

UserDefaults are written to storage as a plist (may be text or binary) any credentials are written out as plain text. If the file system is compromised so are any credentials stored there.

The App Sandbox by default locks down the file system, but can be escaped. You shouldn’t need to worry about this with App Store apps (but you also cannot ensure that the app you run doesn’t have a Sandbox escape).

If the Sandboxed application is signed with the same Team ID as the targeted application and has the right entitlements, the customer may not get asked to approve Keychain access. Even then the request dialog can be confusing, I see this all the time.

In theory, a Sandbox escape is more likely if the attacker has direct access to the device and can manually install an application without it being approved by the App Review.

IIRC it is also possible for a Sandboxed application to have entitlements which would allow it to read other applications UserDefaults, again it needs to be signed with the same TeamID as the targeted application.

In summary, my honest advice would be to encrypt the token myself, this will negate either of these possibilities and would require the app to be debugged to see what the encryption parameters are.

Which increases the workload to compromise a social media account, while it may actually be easier to simply brute force an account or use a phising scheme to obtain credentials.