winapicredential-providerswindows-security

Pre validate user with LsaLogonUser when offline


I have a credential provider with MFA codes, and offline MFA codes. Of course, the credential provider is a DLL and is running in a system application under NT Authority\System. I'm not trying to modify the token in any way. I figure if it's running in the logon process, it probably has all the permissions it needs...although that may not be true...

I want to pre-validate user accounts so that we don't force the user to do MFA if he entered a bad username or password. It is annoying when you go through the MFA process, serialize the creds in the interface callback ICredentialProviderCredential::GetSerializaion and then it reports bad creds in ICredentialProverCredential::ReportResults and you have to repeat the cycle...at least in our current flow.

I am calling LsaLogonUser with the logon type as SECURITY_LOGON_TYPE::Interactive and the authentication package being MSV1_0_PACKAGE_NAME. If the computer is online it always works -- returning STATUS_NOERROR for good creds and STATUS_LOGON_FAILURE for a failed logon. I have even tried some of the other logon types, thinking maybe SECURITY_LOGON_TYPE::CachedInteractive logon type would work...but that returns an unsupported error code for both correct and bad passwords.

If I go offline, Local accounts still pass the LsaLogonUser call, however, AzureAD accounts fail. I think I have tested AD joined machines disconnected, but need to go back and test. Right now I'm just trying to solve the AzureAD issue.

I am doing a connect untrusted to populated the first argument of LsaLogonUser

... LsaConnectUntrusted maybe could be problem???

LsaLoginUser w/ Local Account LsaLogonUser w/AzureAD account
Online Success Success
Offline Success Failure

--------------------- Edit Add Info -------------------------

From the outset I knew some of these logon types would be incorrect, but decided to test them all--in for a penny, in for a pound.

LogonType Error Msg NtStatus NtSubstatus
Interactive The user name or password is incorrect. (1326) c000006d 0
Network The user name or password is incorrect. (1326) c000006d 0
Batch The user name or password is incorrect. (1326) c000006d 0
Service The user name or password is incorrect. (1326) c000006d 0
Proxy A logon request contained an invalid logon type value. (1367) c000010b) 0
Unlock The user name or password is incorrect. (1326) c000006d 0
NetworkClearText The user name or password is incorrect. (1326) c000006d 0
NewCredentials A logon request contained an invalid logon type value. (1367) c000010b) 0
RemoteInteractive The user name or password is incorrect. (1326) c000006d 0
CachedInteractive The request is not supported. (50) c00000bb 0
CachedRemoteInteractive The user name or password is incorrect. (1326) c000006d 0
CachedUnlock A logon request contained an invalid logon type value. (1367) c000010b) 0

Solution

  • This is going to seem stupid. I have code in places where if it is joined to AzureAD, checks for username, and then substitutes AzureAD for the domain if an email is detected. If the computer is not AD joined, then the default "domain" is WORKGROUP... maybe no bueno...

    However, the code path did not substitute AzureAD and so it was failing when disconnected...

    HOWEVER... If the machine is connected, LsaLogonUser() can verify the creds if the domain is WORKGROUP. To me, that's even stranger...

    Bottom line, ensure the domain is set to AzureAD when calling the function when using an AzureAD account.