LAContext and smart cards

In one of our applications we use LAContext's evaluatePolicy:localizedReason:reply: to authenticate a user. This works pretty well with both username/password and Touch ID. Now we have a request to add support for smart cards and I wonder if this is possible using LAContext. Otherwise I would use Authentication Services, although that might be a bit overkill since we don't need to request any rights, we just want to see that the user has been successfully authenticated. Or is there a better way? Any help would be greatly appreciated.

Thanks, Marc

Answered by DTS Engineer in 821093022

Unfortunately that didn’t pan out.

I talked to the Local Authentication (LA) team about this and they confirmed there’s no supported way for LA to present the Use PIN button that Keychain Access presents via Authorization Services. LA has some support for smart card PINs, but this represents a gap in that support.

We’d welcome an enhancement request for this feature. I encourage you to file that, with details about your specific use case.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I noticed that the Keychain Access utility uses exactly what I am looking for if I delete something from the Keychain. Please see the attached screenshot. Any idea if this can be done using Local Authentication?

Written by marc_thielemann in 819320022
I noticed that the Keychain Access utility uses exactly what I am looking for …

That UI is being presented by Authorization Services. Here’s how you can replicate it with your code:

let rightName = "com.apple.trust-settings.user"
let err = rightName.withCString { namePtr in
    var item = AuthorizationItem(name: namePtr, valueLength: 0, value: nil, flags: 0)
    return withUnsafeMutablePointer(to: &item) { itemPtr in
        var rights = AuthorizationRights(count: 1, items: itemPtr)
        return AuthorizationCopyRights(ref, &rights, nil, [.extendRights, .interactionAllowed], nil)
    }
}

I was hoping that the new Local Authentication right mechanism might help with this situation. For example, with code like this:

let requirement = LAAuthenticationRequirement.biometry(fallback: .devicePasscode)
let right = LARight(requirement: requirement)
do {
    print("will authorise")
    try await right.authorize(localizedReason: "Testing only.")
    print("did authorise")
} catch {
    print("did not authorise, error: \(error)")
}

However, in this case the button is Use Password rather than Use PIN )-:

I’ve got one more thing I want to try. I’m off to do that now and I’ll post an update when I’m done.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

Unfortunately that didn’t pan out.

I talked to the Local Authentication (LA) team about this and they confirmed there’s no supported way for LA to present the Use PIN button that Keychain Access presents via Authorization Services. LA has some support for smart card PINs, but this represents a gap in that support.

We’d welcome an enhancement request for this feature. I encourage you to file that, with details about your specific use case.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for the information. Filed an enhancement request FB16312095. Hope this helps.

Best regards, Marc

Is there another way to authenticate a (non-admin) user with a smart card? I tried a few things using Authorization Services, but it only worked well with admin users. I know that Authorization Services is used to request authorization for something, but can I misuse it in some way to accomplish what I want?

Written by marc_thielemann in 821080022
I know that Authorization Services is used to request authorization for something

Right. But is that a blocker? Speaking abstractly, you’re requesting that the user enter their PIN because you want to authorise some operation, right? Or is there something more subtle going on?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@DTS Engineer If you want to see it that way, you're right, of course. I am currently just wondering which right I should request. I first thought of authenticate-session-owner, but that only works if the user is an admin. com.apple.trust-settings.user would generally work, but the text that is displayed during authentication is somewhat misleading. Is there something I can use or should I create a custom right for this? Many thanks in advance for your support. I really appreciate it.

Written by marc_thielemann in 821203022
I am currently just wondering which right I should request.

Define your own; see TN2095 Authorization for Everyone.

It’s been a long time since I’ve done this, so it’s possible that things won’t go as smoothly as they did back in… gosh… 2008. AFAIK this stuff still actually works though. I recommend an initial proof-of-concept test before you commit to the idea.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi Quinn!

This works pretty well. Just wondering if it would be possible to check if a smart card is available. Then I could switch to Local Authentication (Touch ID) otherwise. Thanks for helping me with this.

Best regards, Marc

Written by marc_thielemann in 822680022
This works pretty well.

Cool.

Written by marc_thielemann in 822680022
Just wondering if it would be possible to check if a smart card is available.

CryptoTokenKit will tell you whether a smart card is available, but that’s only part of the story. You need to know whether its paired to the user’s account. I think you can get that info from the user’s Open Directory record, but I don’t have time to try that out today.

If you dump the directory record (using dscl) before and after pairing the smart card, what difference do you see?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

If a smart card is paired to the account, the AuthenticationAuthority contains an additional entry like tokenidentity;29A5F37DB3E09402BFD231B306D5AB4099EBFE4E.

Yeah, I had a vague recollection that it was set up this way.

I think that’s all you need to answer your current question. Although it’s best not to run dscl itself, but rather access this record property with the Open Directory framework. For an example of how to get started with that, see this post.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

During my testing it turned out that even if using Authorization Services, the Mac asks me for Touch ID. I always had in mind that this would only work using Local Authentication. So it seems that I don't have to use either one or the other but can build everything completely using Authorization Services. It asks me for Touch ID or PIN if a PIV token is connected, otherwise it asks me for Touch ID or Password.

LAContext and smart cards
 
 
Q