How to fire device PIN dialog? - ios

I working on an app that is designed to be protected from unauthorized access (like, for instance, bank apps do). There are two protection options: by using biometrics (default one) and by user password. I wonder, what the best practices are to handle the situation when a user forget thier password.
I'm thinking to prompt user to enter device PIN in order to remind them the password, but I can't figure out how to do that.

I guess it really depends on exactly how sensible the information is and how you're currently storing/validating the password. But assuming your threat model is okay with a user being able to get access back just with the current device password, you could use the keychain API (not the friendliest of APIs) and store some kind of flag. When adding such item you would use SecAccessControlCreateFlag.devicePasscode which will always prompt the user for their iPhone passcode before accessing such entry. So say the user needs to reset it, if you're able to access the keychain entry, you know they entered the right device passcode and thus you should allow them to reset their app password. The main caveat would be that the user disabling their passcode or not having one would invalidate your flag so they would be locked out forever if they ever forget their app password. Of course there's a lot of additional nuance to the Keychain like whether the items get synced to other devices or not, when it's available, etc. but hopefully this is somewhat useful.

Related

iOS fingerprint device PIN Prompt while kSecAccessControlBiometryCurrentSet flag is set

I'm working on a fingerprint Authentication using the keychain methods from iOS and can't manage to not show the pin proposal to be displayed after an error.
I'm using the flag kSecAccessControlBiometryCurrentSet which should only allow biometrics authentication.
So for the first prompt it works well and I didn't get the possibility to enter the passphrase but as soon as an authentication fails, the prompt changes and allow the user to enter his code. I would like to block this and only allow fingerprint authentification through that prompt.
There's the code I'm using: https://github.com/xavistas/cordova-plugin-touch-id/blob/noPinCode/src/ios/TouchID.m
If you have any idea, feel free to share :) !
I finally found the solution but it isn't really trivial.
You have to know that the keychain is never cleared for your application, even if you uninstall it.
So basically, if you tried one time to with a flag, let's say kSecAccessControlUserPresence, until you manually specify that you want to clear the keychain entry, this flag will stay stored.
And basically, even you if you "create the keychain token" each time the user connects to the app, it will not replace the keychain entry.
I hope it will help some of you !

Is it enough to save Pin code (string) value to iOS Keychain to be secure?

I am working on the app that require protection screen for the app.
This screen looks like :
I already done all features expect one. It is proper saving of the pin code.
I read about iOS Keychain and think it is quite suitable approach to save sensitive information.
But I would like to hear opinion from others is it enough? Or what should i use to protect this (pin code) information.
Now it is working like:
Set
Pin -> Keychain
Get
Keychain -> Pin
Also I consider hashing:
Set
Pin->Encode->Keychain
Get
Keychain->Decode->Pin
Saving a PIN is similar to saving a user password - one should never do this in plain text even when you store it protected like in the keychain.
At least save it as salted hash, better use a password hashing scheme (one-way security function designed for processing passwords and PINs) like PBKDF2, bcrypt, scrypt or Argon.
In most cases the keychain should be enough. But there is no 100 percentage solution. If an attacker has access to the hardware and software you can only make it harder to get the data, not impossible.
That means in your case an attacker already needs access to the device and the device pin code / touchid (if set) to install a jailbreak. Only then it's possible to get access to the content of the keychain and your stored data inside.
An additional encoding of your keychain data requires to store the key for the encode/decode somewhere. You have to save it somewhere else, e.g.in the user defaults, but the keychain already has the highest security level. Encoding makes sense for the real user data (the data you want to secure with the pin: access token, file encryption password, ...), because for these data it may be importend to destroy them in app deinstall/reinstall process. The user defaults will be removed when deinstall, the keychain not.
Scenario: User deletes app and sell his/her phone without resetting it in device settings. Buyer installs jailbreak -> old data in keychain should be garbage/unreadable.
Conclusion:
Think about it: What user data do you wanna secure with the pin? These data are also located inside of the keychain, even if it's only an access token for web requests or a password for an encryption. You don't need a higher security level for the pin than for your data ;)
In case of a pin your solution should be enough. But it's imported that your real user data should use the same security level or a higher one.
Update
There is a higher security level than the keychain: "Secure Enclave". It's mainly used for saving the touch id informations. Apple do not documented it, so I wouldn't recomend to use it yet.
There is a project called Tidas to make it accessible for the community.

How Do I Force An iOS TouchID To Re-Authorize After Each Access, or Check If It is Unlocked?

OK. I suspect I just need to be directed to the appropriate "M" for "RTFM." I'm not new to iOS, but fairly new to keychain use. I am using a good keychain wrapper called "FXKeychain."
I have an app that includes a login, with a password stored in the default keychain.
I use TouchID to validate the user and fill in the password.
In order to do this, I display a "thumbprint" button, with an IBAction handler that runs the standard code:
self.s_authenticationContext.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: "Yo. Gimmie ur thumb.", reply: self.touchIDCallback)
The issue is, that once it is unlocked, subsequent touches of the button, using the above, skip the alert, and simply fall through.
This is an issue because the same button is displayed, even after the user is validated. I'd like to either:
Re-lock after entering the password, so the user must re-authenticate each time (preferred), or
Display a different button image that indicates the thumbprint is no longer necessary.
That means that I need to:
Find a way to re-lock the TouchID, or
Find out if the user is unlocked.
Any ideas?
Thanks!
It is your authentication context rather than the keychain that is 'unlocked'. If you allocate a new authentication context before calling evaluatePolicy then the touchID dialog will be shown again.
You can, however, actually use touchID to authenticate access to a keychain item directly. The Apple sample code demonstrates how to do this - https://developer.apple.com/library/ios/samplecode/KeychainTouchID/Introduction/Intro.html#//apple_ref/doc/uid/TP40014530-Intro-DontLinkElementID_2

How to identify users in IOS

We are developing an app for IOS.
Is there anyway I can check that the "identifierForVendor" that the device sends me in it's first connection to my server is actually valid?
If there isn't a way, how can I make sure someone is not just sending POSTS to my server and so making me create Device DB Objects that don't really exist?
The only secure way I have found is:
1- Make the App ask for a Device Token to APNs
2- Send it on it's first connection to my server.
3- Check with APNs Feedback Service
4- If token is ok, create the Device DB Object and continue from there.
Apple should let you know some Device-Vendor Id in a communication between Apple and your server every time someone downloads an app.
Thank you.
The simplest solution would be to append the "identifierForVendor" with something you can identify from your app. For example, if you append an alphanumeric string that looks like this: "A1B2C3D4E5F6G7" to be "A1B2C3D4E5F6G7-fromMyApp", then there is no way for someone to know what the custom appended string is, unless they have access to your code.
Of course there are more complex solutions, if you are genuinely concerned of people going so far as to monitor traffic from your app just to find the string.
Are you aware that registering for remote notifications prompts the user if they want to allow remote notifications for the app. If they choose no, there is no token generated.
Besides, they can sniff the token off the wire. Do you plan on tracking abuse and blocking users based on their token? Do you know that some actions cause a new token to be generated, such as resetting the device?
You can generate a unique ID (UUID) or use identifierForVendor, and store it in the user's key store and use that to track by device. It's still anonymous, and resetting the device resets this, but if you're tracking abusers, you can block them and they have to reset their device to try it again. This isn't much different from an APN token. It can still be sniffed, and they can still reset it. But at least the user doesn't have to say yes to allowing remote notifications.
If you're sending any kind of token, you should use HTTPS (SSL/TLS), not to protect the user from themselves (they can still sniff the token by doing their own man in the middle attack unless you are verifying the identify of the server), but this is to protect people from malicious users on the same network. You don't want to block some innocent user because they happened to use your app on a public network and inadvertently shared their token.
Of course, if we're talking a jail-broken device, all bets are off.

Inviting users to an IOS app

After registration, our app prompts users to invite her friends (aka phone contacts) to use the app too. This allows us to send an email/sms to the useer's contacts with some sort of invitation key. Works fine for a web version app, just embed the key in the url you provide in the invitation.
I'm having trouble figuring out how to make this work smoothly with IOS only. It would be brilliant if I could send the invitee a link to appstore.apple.com/myapp?registrationKey=abcXYZ and have the key magically available to my app once it's installed, but I guess this is a lot to hope for?
The obvious way around this is to make the user manually enter their registration key on first launch, but this seems less reliable and (to my mind) adds friction to the UX.
Has anybody come up with something clever to get around this?
Here is what is flowing through my brain on how to solve this solution, please note, I have not vetted, psudeo-coded, coded, or applied this theory.
Since you will know who is being sent an invitation, save that data to your database with a relationship to the user sending and a unique id to the user being invited (email address if its in the contact's card). When new users sign up scan the database for invitations, if one is found present it to the user asking We're you referred by <existing user>? Once the new user selects their response continue through the registration process, updating the relationship table accordingly and applying any extra settings you need to for the referral.
This combines automatic referral tracking with referral codes for a basic, straight-forward, almost (but not quite) fool proof method to make sure referrals are linked to the right users.
As far as I can tell, the App Store provides an information firewall between an invitation and the installed app.
The closest workaround I've seen is the following:
email link sends you to your website
the website logs reference information in the URL and the IP address
the website instantly redirects you to the App Store (if iOS detected)
user installs the app
user loads the app
app contacts your website, IP addresses matched ... BINGO
Obviously not a secure method though.
There are many failure cases:
business networks commonly share IPs
home and mobile networks release and reuse IPs
The more is frequently used to resolve cases where its good enough to know that the user 'almost-certainly' was referred to download app by the email.
For example, it can be a good mechanism to prompt the user with a "who do you know" question in an app and limit the options based on the (IP+reference) data. If they pick the original poster, then maybe that's good enough, and then you can attach any other data that the inviter provided.
(Full disclosure, currently work at Branch)
The best solution to this is to fingerprint a user. This requires you to do the following steps:
For each user, using your own domain, generate a link for said user. So, right when they complete registration, generate their unique URL, that contains the invitation key.
For anyone clicking this link, they will redirect to Safari first. When they do, capture their IP address and iOS operating system version from the headers and user-agent.
Save this data on your server, and set window.location to your iTunes url.
If the user downloads and consequently opens, inside AppDelegate.m, send a message to your server with the IP address + major/minor/min version you collect upon app launch. If it matches with what you have on the server, you can now pass that invitation key back to the new user.
It's not perfect, and has the ability to misattribute. You could also use branch.io, where all of this is taken care of (link-generation, fingerprinting a user, attribution). Branch also drops a first party cookie and ties it with the device level ID, so attributions are much more accurate.

Resources