UIDevice-PasscodeStatus icon indicating copy to clipboard operation
UIDevice-PasscodeStatus copied to clipboard

sometimes one of my users says it's not accruate.

Open sunuslee opened this issue 9 years ago • 15 comments

one of my users with iPhone 5S, iOS(8.3) sometimes find that passcodeStatus is not accurate, is there anything wrong? or what i need to be notice?

sunuslee avatar Jun 26 '15 02:06 sunuslee

I haven't tested this extensively myself as it was just something that I created off the back of adding TouchID support to one of my apps.

The readme does explain that it uses a strange technique of testing the Keychain to guess if the passcode is enabled or not so i'm not surprised that there might be some edge cases to it.. That is why the "unknown" enum is there as there is the potential for this to fail.

Do you have any more info about the scenarios where it is inaccurate?

liamnichols avatar Sep 03 '15 14:09 liamnichols

most of the time, i use this check when app is just about to launching or app just about to bring back to foreground . maybe in viewWillAppear. i am not sure if that's related.

now, i use this library plus LAContext's canEvaluatePolicy:error: to double check passcode status. for example, if user's touchid is enable, then he must have passcode enable.

sunuslee avatar Sep 17 '15 05:09 sunuslee

Hmm ok... When you say not accurate, is it just reporting unknown or incorrectly reporting either enabled or disabled?

liamnichols avatar Nov 20 '15 10:11 liamnichols

i consider disabled and unknown are all disabled.

so , i get disable or unknown. when user's passcode is actually enabled

sunuslee avatar Nov 25 '15 07:11 sunuslee

Disabled and Unknown mean two different things... It could be unknown for a number of reasons but still be present on the device.

From my testing, if you're checking it on the main thread (of a UIApplication, not an extension etc) while the application is active in the foreground then you always get either enabled or disabled back.

Because it's such a complicated way to work out if the passcode is active, there is always a chance that it can fail. That's why I included the unknown flag. I'd advise you take Unknown into account and handle it separately to the Disabled flag.. Not really sure of any other solutions I'm afraid.

Sent from my iPhone

On 25 Nov 2015, at 07:25, sunus [email protected] wrote:

i consider disabled and unknown are all disabled.

so , i get disable or unknown. when user's passcode is actually enabled

— Reply to this email directly or view it on GitHub.

liamnichols avatar Nov 25 '15 07:11 liamnichols

ok, so , could you tell me what might cause "unknown" state? i will add more check on that

sunuslee avatar Nov 27 '15 05:11 sunuslee

We specifically return this cause in a few places:

  1. if you're not on iOS 8 or higher
  2. if you're in the simulator
  3. if we're unable to create the access control item (if SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kNilOptions, &sacError) returns NULL)
  4. if we don't get errSecDecode or errSecSuccess back when we add the item (calling SecItemAdd())

It's most likely to be because of 3 or 4..

Best practice is to make sure that you call it on a main thread, while the app is active and not in an extension. I don't know of any other reasons why it might fail but you could try looking on Google/SO To see why the functions in 3/4 could fail?

Have a look at the code to see what they're doing..

Hope it helps

Sent from my iPhone

On 27 Nov 2015, at 05:11, sunus [email protected] wrote:

ok, so , could you tell me what might cause "unknown" state? i will add more check on that

— Reply to this email directly or view it on GitHub.

liamnichols avatar Nov 27 '15 15:11 liamnichols

It seems that in iOS9.2 is almost never detecting when it is disabled. Have you tried with the last version? I have an iPhone6 and it almost always showing UNKNOWN when it is disabled.

kasas avatar Jan 14 '16 19:01 kasas

I'm also receiving "unknown" on iOS 9.2. Tracing through I'm seeing that SecItemAdd is returning errSecAuthFailed. Changing line 71 from if (status == errSecDecode) { to if (status == errSecDecode || status == errSecAuthFailed) { appears to make it behave as I expect on 9.2. I haven't tested (and can't test) regressions on other OS versions.

brianhv avatar Feb 25 '16 04:02 brianhv

Added pull request #9 with this change.

brianhv avatar Feb 25 '16 04:02 brianhv

Following up from #9, I didn't see the comments here.. @kasas, can you expand upon "almost never"? Did you work out if it ever did report correctly?

liamnichols avatar Feb 25 '16 13:02 liamnichols

Have you guys checked out LocalAuthentication.framework since iOS 9? There are some new APIs in the header that aren't documented in the class reference (sigh).

Specifically the LAPolicyDeviceOwnerAuthentication case on LAPolicy.

From the header:

/// Device owner was authenticated by Touch ID or device passcode.
///
/// @discussion Touch ID or passcode authentication is required. If Touch ID is available, enrolled and
///             not locked out, user is asked for it first, otherwise they are asked to enter device
///             passcode. If passcode is not enabled, policy evaluation will fail.
///
///             Touch ID authentication dialog behaves similarly as the one used by
///             LAPolicyDeviceOwnerAuthenticationWithBiometrics. However, instead of "Enter Password"
///             button there is "Enter Passcode" button which, when tapped, switches the authentication
///             method and allows users to enter device passcode.
///
///             Passcode authentication will get locked after 6 unsuccessful attempts with progressively
///             increased backoff delay.
LAPolicyDeviceOwnerAuthentication NS_ENUM_AVAILABLE(10_11, 9_0) = kLAPolicyDeviceOwnerAuthentication

I've not tested, and i'm not sure if I understand it correctly but this means that you could potentially do something like this:

LAContext *context = [LAContext new];
NSError *error;
BOOL passcodeEnabled = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error];

if (error != nil) {
    // error
} else if (passcodeEnabled) {
    // user has their passcode set
} else {
    // users passcode is not set
}

to work out if the passcode is set?

Might be worth checking it out... If you do, let me know how it goes

liamnichols avatar Feb 29 '16 17:02 liamnichols

I can confirm that the LAPolicy's flag LAPolicyDeviceOwnerAuthentication works for testing if passcode has been set.

heikkihautala avatar Mar 16 '16 11:03 heikkihautala

In that case, use that if you only care about iOS9+. I'll look at making an update to use LAContext if you're on 9 then fallback to the keychain test for 8 if I get time

Sent from my iPhone

On 16 Mar 2016, at 11:40, Heikki Hautala [email protected] wrote:

I can confirm that the LAPolicy's flag LAPolicyDeviceOwnerAuthentication works for testing if passcode has been set.

— You are receiving this because you commented. Reply to this email directly or view it on GitHub

liamnichols avatar Mar 16 '16 13:03 liamnichols

Confirming what @heikkihautala said, plus wanted to note that LAPolicyDeviceOwnerAuthentication also works on Simulator. (iOS9 restriction still applies)

sschale avatar Apr 18 '16 23:04 sschale