Is it possible to detect if an Apple Watch has a passcode set?

I need to know if an Apple Watch user has a passcode set before we can show sensitive data in a View.

Is there a way to check for this?

LAPolicy is unavailable on the Watch and I cannot check deviceOwnerAuthenticationWithWatch from a paired phone only from a Mac.

Accepted Reply

Eskimo, thank you so much for the suggestion. With that I think I'm now on the right track.

I have the following options set when adding the item to the keychain:

Code Block swift
        let flag = SecAccessControlCreateFlags.userPresence
        let sacResult = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, flag, &error)

and have

Code Block swift
            kSecUseAuthenticationUI as String: kSecUseAuthenticationUIFail

in the attributes for SecItemCopyMatching

On my own watch with passcode on I get the "User interaction is not allowed" error, which seems correct.
I didn't see that in the simulator where the passcode cannot be set - that shows "No error."

I need to verify with passcode off on a device but this looks really promising. Thank you

  • Hey @pawpoise,

    I am trying to achieve the same thing I am trying the following

        var query: [String: Any] {        return [kSecUseAuthenticationUI as String: kSecUseAuthenticationUIFail]     }            let flag = SecAccessControlCreateFlags.userPresence

         var accessControlError: UnsafeMutablePointer<Unmanaged?>? = nil

         var result: AnyObject? = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, flag, accessControlError)

         let status = SecItemCopyMatching(query as CFDictionary, &result)                 switch status {     case errSecSuccess:       print("keychainItem")     case errSecItemNotFound:       print("errSecItemNotFound")     default:       print("error")     }

    this is always hitting the default case with -50 im guessing one of my params are not valid

  • Hey @pawpoise,

    I am trying to achieve the same thing I am trying the following

    `    var query: [String: Any] {        return [kSecUseAuthenticationUI as String: kSecUseAuthenticationUIFail]     }            let flag = SecAccessControlCreateFlags.userPresence

         var accessControlError: UnsafeMutablePointer<Unmanaged?>? = nil

         var result: AnyObject? = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, flag, accessControlError)

         let status = SecItemCopyMatching(query as CFDictionary, &result)                 switch status {     case errSecSuccess:       print("keychainItem")     case errSecItemNotFound:       print("errSecItemNotFound")     default:       print("error")     } this is always hitting the default case with-50` im guessing one of my params are not valid

Add a Comment

Replies

I don’t have time to try this today but I figured I’d pass it along just in case it works (-:

I need to know if an Apple Watch user has a passcode set before we can
show sensitive data in a View.

If you gate access to your view via a keychain item that’s protected with kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, does that do what you want? Ideally the sensitive data should be encrypted with the content of that keychain item but for a quick test you can just see whether the item is available.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Eskimo, thank you so much for the suggestion. With that I think I'm now on the right track.

I have the following options set when adding the item to the keychain:

Code Block swift
        let flag = SecAccessControlCreateFlags.userPresence
        let sacResult = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, flag, &error)

and have

Code Block swift
            kSecUseAuthenticationUI as String: kSecUseAuthenticationUIFail

in the attributes for SecItemCopyMatching

On my own watch with passcode on I get the "User interaction is not allowed" error, which seems correct.
I didn't see that in the simulator where the passcode cannot be set - that shows "No error."

I need to verify with passcode off on a device but this looks really promising. Thank you

  • Hey @pawpoise,

    I am trying to achieve the same thing I am trying the following

        var query: [String: Any] {        return [kSecUseAuthenticationUI as String: kSecUseAuthenticationUIFail]     }            let flag = SecAccessControlCreateFlags.userPresence

         var accessControlError: UnsafeMutablePointer<Unmanaged?>? = nil

         var result: AnyObject? = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, flag, accessControlError)

         let status = SecItemCopyMatching(query as CFDictionary, &result)                 switch status {     case errSecSuccess:       print("keychainItem")     case errSecItemNotFound:       print("errSecItemNotFound")     default:       print("error")     }

    this is always hitting the default case with -50 im guessing one of my params are not valid

  • Hey @pawpoise,

    I am trying to achieve the same thing I am trying the following

    `    var query: [String: Any] {        return [kSecUseAuthenticationUI as String: kSecUseAuthenticationUIFail]     }            let flag = SecAccessControlCreateFlags.userPresence

         var accessControlError: UnsafeMutablePointer<Unmanaged?>? = nil

         var result: AnyObject? = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, flag, accessControlError)

         let status = SecItemCopyMatching(query as CFDictionary, &result)                 switch status {     case errSecSuccess:       print("keychainItem")     case errSecItemNotFound:       print("errSecItemNotFound")     default:       print("error")     } this is always hitting the default case with-50` im guessing one of my params are not valid

Add a Comment