Local Authentication on iOS
Overview
During local authentication, an app authenticates the user against credentials stored locally on the device. In other words, the user "unlocks" the app or some inner layer of functionality by providing a valid PIN, password or biometric characteristics such as face or fingerprint, which is verified by referencing local data. Generally, this is done so that users can more conveniently resume an existing session with a remote service or as a means of step-up authentication to protect some critical function.
As stated before in chapter "Mobile App Authentication Architectures": The tester should be aware that local authentication should always be enforced at a remote endpoint or based on a cryptographic primitive. Attackers can easily bypass local authentication if no data returns from the authentication process.
A variety of methods are available for integrating local authentication into apps. The Local Authentication framework provides a set of APIs for developers to extend an authentication dialog to a user. In the context of connecting to a remote service, it is possible (and recommended) to leverage the keychain for implementing local authentication.
Fingerprint authentication on iOS is known as Touch ID. The fingerprint ID sensor is operated by the SecureEnclave security coprocessor and does not expose fingerprint data to any other parts of the system. Next to Touch ID, Apple introduced Face ID: which allows authentication based on facial recognition. Both use similar APIs on an application level, the actual method of storing the data and retrieving the data (e.g. facial data or fingerprint related data is different).
Developers have two options for incorporating Touch ID/Face ID authentication:
LocalAuthentication.framework
is a high-level API that can be used to authenticate the user via Touch ID. The app can't access any data associated with the enrolled fingerprint and is notified only whether authentication was successful.Security.framework
is a lower level API to access keychain services. This is a secure option if your app needs to protect some secret data with biometric authentication, since the access control is managed on a system-level and can not easily be bypassed.Security.framework
has a C API, but there are several open source wrappers available, making access to the keychain as simple as to NSUserDefaults.Security.framework
underliesLocalAuthentication.framework
; Apple recommends to default to higher-level APIs whenever possible.
Please be aware that using either the LocalAuthentication.framework
or the Security.framework
, will be a control that can be bypassed by an attacker as it does only return a boolean and no data to proceed with. See Don't touch me that way, by David Lindner et al for more details.
Local Authentication Framework
The Local Authentication framework provides facilities for requesting a passphrase or Touch ID authentication from users. Developers can display and utilize an authentication prompt by utilizing the function evaluatePolicy
of the LAContext
class.
Two available policies define acceptable forms of authentication:
deviceOwnerAuthentication
(Swift) orLAPolicyDeviceOwnerAuthentication
(Objective-C): When available, the user is prompted to perform Touch ID authentication. If Touch ID is not activated, the device passcode is requested instead. If the device passcode is not enabled, policy evaluation fails.deviceOwnerAuthenticationWithBiometrics
(Swift) orLAPolicyDeviceOwnerAuthenticationWithBiometrics
(Objective-C): Authentication is restricted to biometrics where the user is prompted for Touch ID.
The evaluatePolicy
function returns a boolean value indicating whether the user has authenticated successfully.
The Apple Developer website offers code samples for both Swift and Objective-C. A typical implementation in Swift looks as follows.
Using Keychain Services for Local Authentication
The iOS keychain APIs can (and should) be used to implement local authentication. During this process, the app stores either a secret authentication token or another piece of secret data identifying the user in the keychain. In order to authenticate to a remote service, the user must unlock the keychain using their passphrase or fingerprint to obtain the secret data.
The keychain allows saving items with the special SecAccessControl
attribute, which will allow access to the item from the keychain only after the user has passed Touch ID authentication (or passcode, if such a fallback is allowed by attribute parameters).
In the following example we will save the string "test_strong_password" to the keychain. The string can be accessed only on the current device while the passcode is set (kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
parameter) and after Touch ID authentication for the currently enrolled fingers only (SecAccessControlCreateFlags.biometryCurrentSet
parameter):
Swift
Objective-C
Note regarding temporariness of keys in the Keychain
Unlike macOS and Android, iOS does not support temporariness of an item's accessibility in the keychain: when there is no additional security check when entering the keychain (e.g. kSecAccessControlUserPresence
or similar is set), then once the device is unlocked, a key will be accessible.
Last updated