Storing authentication tokens on iOS - NSUserDefaults vs Keychain? - ios

Which is the place I should be storing tokens for when the user logins in to a service? I'm not saving passwords (obviously where I'd use the Keychain) but just the token. A lot of places say just use NSUserDefaults but some people on StackOverflow seem really keen on the Keychain.
Is NSUserDefaults fine?

I would highly recommend you use the keychain - it's exactly what Facebook do for storing their session tokens.
NSUserDefaults is not secure or encrypted - it can be easily opened and read, both on device and when synced to a Mac. So whilst user defaults is a good place for things like preferences and config info, it's not a good place for anything sensitive, like passwords.
Session tokens should almost always treated the same as passwords, so you should store them securely in the keychain, where they'll be encrypted. Apple have some sample code (GenericKeychain) that shows a basic implementation, and you'll find other examples by searching StackOverflow. Hope that's helped you out.

NSUserDefaults can be used without any problems (for tokens!).
Please check documentation https://developer.apple.com/documentation/security/keychain_services
Keychain Services are invented to “secrets” that the user explicitly cares about, i.e. passwords, private keys or even secure notes, i.e. clear credentials. But access tokens are temporary hashes generated after user entered password and have limited time. And even if stolen, the malefactor cannot completely stole the account - the owner can login on another device and previous access token will be reset. So, formally there is no forbiddance to store access tokens in UserDefaults.
The data from UserDefaults can be stolen only if the device is stolen itself, but I think the security level of the content is much lower than the physical device itself. I think user would not worry about the token in that case, but about the device.
However, it’s a good practice to store it in Keychain, but it’s just an excessive (!) usage of security and usually recommended by random users in the Internet and it’s not required by Apple. There is no documentation by Apple there they say that tokens must be stored in Keychain (if you can find one, then please comment one below).
So, the answer is - you can use both. However, if you app is operating with content that costs a lot in contrast to stolen iPhone, then it's better to use Keychain, but it's just a recommendation.

All sensitive data should be stored in the keychain.
UserDefaults is for small pieces of data like user preferences.

Related

Setting credentials in code can still be compromised even after keychain security

I would like to store username, password, auth token in my iOS app so that I can connect to my db, perform operations etc. I notice that the recommended way is keychains. The reason for this is that a malicious hacker if got your ipa by jailbreaking or something else can read your code and look at the username/password.
But my question is once the user logs in and I save their username and password in keychain, I set the credentials in the code itself so how is this secure? If a hacker gets an ipa and opens up the code, they will see where I'm setting the password anyway or if there a place to store this so no one can really see it.
I have been reading a lot about how secure keychain is and I definitely agree it is, but setting the value in keychain has to be done in the code itself which worries me if someone gets the code and can see it.
Reference: https://medium.com/ios-os-x-development/securing-user-data-with-keychain-for-ios-e720e0f9a8e2
You can add an extra layer of protection by detecting if App is running on a jailBroken phone
How do I detect that an iOS app is running on a jailbroken phone?
Also keychain provides protection to passwords or private keys as the data is encrypted.
An application can access only its own keychain items, or those shared with a group to which the app belongs.
https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/02concepts/concepts.html

Storing password in the client side using Appcelerator - Design Approach

I am creating an application using Appcelerator wherein the user needs to enter the username and password to login. Once logged in, the user can enable TouchID for authentication. After logging out, the user can use the TouchID for authentication and use the application.
My flow is that once the username and password is provided, I store those two information in Keychain using the following module iOS Keychain Module. Then I use ti.touchid to authenticate the fingerprint, if success, then I retrieve the username and password from keychain and then send it over HTTPS web service call and login the user to the application.
My query is that, whether this is an acceptable approach.
I am not an iOS developer nor does any ti or keychain terms mean anything to me at all. That's for a start and to reduce the number of down votes i might get.
In terns of security, I would suggest that you imagine obtaining that particular user's phone where you know you have some authentication credentials stored. Let's say I am a user of your app, already logged-in and have my credentials saved somewhere on my device, and you obtain this phone by stealing it from me.
Now, will you be able to access my account in anyway? Will a hacker with access to the physical phone be able to retrieve any information stored in your Keychain storage?
If so, If you can think of anyway to do so, then your approach is not valid.
I understand you want to save users sometime by making sure they can login with just their fingerprint, which is a valid reason to think of such an approach, but you will have to think everything in terms of reverse engineering.
Additional recommendations would be using an on-the-fly hash to store information in the Keychain and making sure to check that before restoring the same. For example, user credentials saved on "home wifi" can be verified with your fingerprint only "at home" on the same wifi network where the same will be invalid on a different network.
i.e)
(keychainItem.x = y) is TRUE ONLY IF (something else)
where this (something else) is something that will prevent hackers from accessing the Keychain even if they have access to the device itself.
I do this myself when programming web applications with stored cookies. I for example use a stored cookie ONLY IF it is being accessed from the same IP it was saved from. Anytime that IP address changes, user will have to re-authenticate even if the cookie values are correct.
Hope this helps.

Using Touch ID on iOS to encrypt data

What I'm trying to do
Basically what I'm trying to do is figure out a way to encrypt data using Touch ID.
Sadly I've not found a way to create an encryptionKey with Touch ID, since the LAContext API only returns a aye/nay response.
Why I'm trying it
I'm implementing different log in methods in an app. The supported log in methods are a password, PIN-code and Touch ID. The user is free to choose whatever log in method he/she wants.
Only the password however, is send to the server which will authenticate the user. As such, only the password is stored in the keychain.
The encryptionKey, used to first encrypt and then store the password in the keychain, is created using whatever method the user chose as log in method.
If the user chose to use a PIN-code, the encryptionKey is derived from that PIN-code, the same can be said when the user chose a password as log in method.
My question is:
How can I fit Touch ID in this picture?
I've searched on the internet, but only found what I already feared.
Since iOS only returns a true or false from the Secure Enclave, it's impossible to create an encryptionKey.
I know the keychain is encrypted by itself, but for security reasons (please don't elaborate on this) I need an encrypted password stored in the keychain.
EDIT:
The reason behind storing data encrypted in the keychain is because the keychain can be breached by jailbreaking a device.
And since the app I'm working on allows users to view (mostly) corporate sensitive data, I need to take even jailbreaking into consideration.
Use the kSecAccessControlTouchIDCurrentSet or kSecAccessControlTouchIDAny keychain access control attributes to protect your encryption key in the keychain. Using this API will fail if the user does not have Touch ID enabled (or the device does not support it), and using kSecAccessControlTouchIDCurrentSet will fail if the user modifies the set of fingerprints. In case of failure, you can then fallback to your normal authentication UI, such as pin code or password entry.
See the WWDC 2014 711 Keychain and Authentication with Touch ID talk and WWDC 2015 706 Security and Your Apps for more information.
As a general note, do not store data in the keychain. You should only store passwords, encryption keys or credentials, and use those to decrypt data stored on the disk.
I know, this question was posted back in 2015, but I researched for the same problem. As Far I know, it's actually not possible.
I have found this Quote on the 1Password website concerning this topic:
Don’t jailbreak your device. Someone with physical access to your device could theoretically access the secret that 1Password stored in the iOS Keychain. However, that would require unlocking the device, jailbreaking the device (so that something other than 1Password can read the iOS Keychain data that belongs to 1Password), and defeating the obfuscation of the Master Password. If you jailbreak your device, you are willingly defeating one of the strongest defenses against such an attack.
So, simple answer: It's not possible :(

IOS Keychain Service

I'm new to iOS development and programming, so please bear with me.
Correct me if I'm wrong but, conceptually, an app can access any items in the Keychain that are associated with the app. It is my understanding that hackers can manipulate the code of an application like "Jailbreaking" to do the hacker's bidding.
In that case, is it possible for the hacker to simply access all the elements of the Keychain by adding additional code?
For example, if my app is checking authorization by comparing the inputted value with the Keychain stored password, could the hacker simply modify the code to get the Keychain stored password? If so, how do you guard against this?
Yes. Anyway, you should be storing the password hash, not the password.
You cannot protect the user against themselves. It's their data. You can't keep them from reading their own data.
The alternative is to store data on your server instead of on the device.

How to store non-standard web authentication?

In the web API my app communicates with, the authentication process is designed in the following way:
The user enters the name of the group that he/she belongs to.
The server sends the list of group members.
The user chooses a user name and types a password.
My app sends a hash constructed of the group id, user id and password to the server to validate the credentials and in case of successful validation uses this hash in further transactions.
Having this process, I do not get standard NSURLConnection messages like connection:canAuthenticateAgainstProtectionSpace: or connection:didReceiveAuthenticationChallenge:.
I can deal with it per se, but when it comes to securely storing the credentials, I get confused. Is there a way to do this via some built-in iOS SDK methods or I have to write the hash in a file manually, for example? What's the proper way?
The keychain seems the best option to store the user's credentials/hash.
Check out http://developer.apple.com/library/mac/#documentation/Security/Conceptual/keychainServConcepts/iPhoneTasks/iPhoneTasks.html
And https://github.com/ldandersen/scifihifi-iphone/tree/05e64ff2814a8192c43f1f81eb8e09dc3764fa18/security
Be aware that while the keychain is probably the safest place in iOS to store this kind of data, it isn't entirely secure. But considering the data you want to store, it's probably well enough.
Edit: Look at http://overhrd.com/?p=208
You'd be able to access the data on your keychain with simple calls of this nature:
[Keychain setString:#"hashhashhash" forKey:#"userHash"];
// later on…
[Keychain getStringForKey:#"userHash"];

Resources