8

I'm integrating TouchID into my app. I'm allowing the user to turn it on and off for security reasons. I want it to auto-turn off when the user adds a new fingerprint. According to Apple, evaluatedPolicyDomainState

This property returns a value only when the canEvaluatePolicy(:error:) method succeeds for a biometric policy or the evaluatePolicy(:localizedReason:reply:) method is called and a successful Touch ID authentication is performed. Otherwise, nil is returned.

The returned data is an opaque structure. It can be used to compare with other values returned by this property to determine whether the database of authorized fingerprints has been updated. However, the nature of the change cannot be determined from this data.

However, I'm adding a new fingerprints and evaluatedPolicyDomainState stays the same.

Any idea on how can I make sure evaluatedPolicyDomainState gets updated or if there's any other way of checking if a new fingerprint was added?

Community
  • 1
  • 1
Cristian Pena
  • 2,139
  • 1
  • 19
  • 31

2 Answers2

25

So after struggling for a couple of hours, I finally found the solution.

    let context = LAContext()
    context.canEvaluatePolicy(.DeviceOwnerAuthenticationWithBiometrics, error: nil)

    if let domainState = context.evaluatedPolicyDomainState
        where domainState == oldDomainState  {
        // Enrollment state the same

    } else {
        // Enrollment state changed

    }

Every time you add or delete a fingerprint, the domain state changes. You need to call canEvaluatePolicy for evaluatedPolicyDomainStateto be updated.

Cristian Pena
  • 2,139
  • 1
  • 19
  • 31
  • Hi Cristian, We also have this requiremnet in our app.Can you please tell what I should assign to oldDomainState Variable? – RXGangam Jan 19 '17 at 08:46
  • When you first request the user to setup touchID, you will use 'context.evaluatePolicy' . If succeeds, then you get the current policy and save it to oldDomainState. – Cristian Pena Jan 23 '17 at 11:24
  • I have used kSecAccessControlTouchIDCurrentSet. Now it is working as expected. – RXGangam Jan 27 '17 at 08:29
  • @CristianPena are you saving it to userdefaults? – waheeda May 12 '17 at 12:51
  • I just save a flag to UserDefaults. The proper value is saved in the Keychain. – Cristian Pena May 12 '17 at 12:52
  • You mean adding fingerprint validation for the Keychain? – Cristian Pena May 12 '17 at 13:00
  • yes, i was just wondering from @RXGangam comment, that she used kSecAccessControlTouchIDCurrentSet to detect change – waheeda May 12 '17 at 13:04
  • @CristianPena - I'm trying to detect the old and current state of evaluatedPolicyDomainState but UserDefaults values keep on updating.Pls help on this. How can save the old evaluatedPolicyDomainState values on user default or keychain and how to make a comparison... variable oldDomainState how to handling from above logic – iCrazyDev May 22 '18 at 06:17
5

Below is the solution to convert the data value of evaluatedPolicyDomainState into string and store it in keychain. If there is any change of Touch Id, then you just need to compare the value of evaluatedPolicyDomainState.

if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) {
    if let domainState = context.evaluatedPolicyDomainState {
        let bData = domainState.base64EncodedData()
        if let decodedString = String(data: bData, encoding: .utf8) {
            print("Decoded Value: \(decodedString)")
        }
    }
}

Note: I didn't test this code for Face Id, I believe it will work for both.

A K M Saleh Sultan
  • 2,403
  • 2
  • 22
  • 28