There are several ways for an application to generate a user’s token via a programmatic Smartcard Logon in Windows. The simplest way is via a call to LogonUser() which typically takes credentials via the user’s password. You can also utilize LogonUser() to do a SmartCard logon by marshaling the SmartCard Certificate on the system with the user’s PIN though the CredMarshalCredential API – http://msdn.microsoft.com/en-us/library/windows/desktop/aa374801(v=vs.85).aspx.
The LogonUser API is just a wrapper around LsaLogonUser() so internally when using LogonUser() + CredMarshalCredential(). Your application can do the same programmatic Smartcard logon directly yourself via the KERB_SMART_CARD_LOGON structure – http://msdn.microsoft.com/en-us/library/windows/desktop/aa378133(v=vs.85).aspx. with LsaLogonUser().
In addition, it is possible to map several Windows Users to a single Smartcard. Windows will display the following User Interface.
To programmatically implement a Smartcard Logon where it is mapped to multiple Windows users can be done via LsaLogonUser() with the KERB_CERTIFICATE_LOGON structure – http://msdn.microsoft.com/en-us/library/windows/desktop/bb545680(v=vs.85).aspx.
Is there any reason why you would choose to do a programmatic logon using LsaLogonUser() instead of LogonUser()?
The only reason is if you are doing this from the LocalSystem security context or you need to do a smartcard logon where the smartcard is mapped to multiple users.
LogonUser() for smartcard logons doesn’t work for the LocalSystem Account. Other than that, LsaLogonUser() has stricter security requirements such as require the SeTcbPrivilege and it is much more complex.
I would choose the LogonUser() route myself since it is simpler and I like simple code.