1

I need my users to input their windows username and password in my application and validate that the credentials are correct, because the role the user should have in my application is mapped to the windows usernames.

(Background: This is an application running on industrial machinery, and the user actually logged into windows is a generic machine user, and the user logging of and on is not feasible). So I cannot just query the currently logged in user and go from there - the user in my software needs to change during the lifetime of the windows login session).

Following Microsofts advice here

The general approach of dealing with credentials is to avoid them and instead rely on other means to authenticate, such as certificates or Windows authentication.

I try to avoid handling the user's password myself.

So I tried using creduipromptforwindowscredentialsw, and while this provides me wit a login window without me handling the credentials, it seems it does not validate the credentials, I can enter anything.

Is there a way to prompt the user for their windows login and just get Username, Domain and "password was correct"? Without ever handling the password in my application?

EDIT to clarify: I do not want or need impersonation. The code can run as the machine user, thats fine. I just want to have a user enter credentials, and get feedback if the credentials were valid and what the username was. With this, my application can grant access to some features that are only accessible to this user.

If I were to handle the passwords myself, my way would be to use DirectoryService to just authenticate against LDAP and be done with it. But I want to avoid having the cleartext passwords in my application if possible.

user3696412
  • 1,321
  • 3
  • 15
  • 33
  • try this: https://stackoverflow.com/questions/1168571 - the only code to run is than a `isCorrect = true;` – Rand Random Aug 04 '23 at 11:21
  • Looks like this would also work: https://learn.microsoft.com/en-us/windows/win32/api/wincred/nf-wincred-creduiconfirmcredentialsa – KG-DROID Aug 04 '23 at 11:25
  • @KG-DROID No, it won't. This function does not validate credentials (as the second paragraph of the documentation states), but is for a program to tell windows if the previously entered credentials were valid. – user3696412 Aug 04 '23 at 11:30
  • @RandRandom Can you elaborate which of the answers you mean? – user3696412 Aug 04 '23 at 11:31
  • The idea is to use a 3rd party authentication service. for example Windows authentication or Google OAuth etc. When the user has to create an account for your application in order to use it then why don't ask him to create a Windows or Google account? That's the best solution (in terms of security). It will also save you a lot of work, resources and responsibility (e.g. to maintain your authentication system). –  Aug 07 '23 at 18:27
  • Would you accept a solution where the password is handled in your code as plain text and then is guaranteed to be deleted from the process memory? – SNBS Aug 09 '23 at 12:10
  • If your client can not guarantee the change of their security policy e.g. by creating a Windows account for each person that is officially authorized to operate the application you must rely on some OAuth API like Windows and/or Google and/or Facebook. Creating those accounts is the responsibility of the company's system admins. Simply implement OAuth authentication. OAuth requires internet connectivity to communicate with the OAuth service. If that's an issue you must constraint a Windows user account per authorized user. There is no other safe solution than that. –  Aug 14 '23 at 08:11
  • Just to make the point, account creation must be delegated to the admins using the official service API e.g. Windows settings. This is not the responsibility of your application. –  Aug 14 '23 at 08:13
  • To bad that the bounty didn’t result in a different answer, good luck on your project anyway – Rand Random Aug 16 '23 at 15:23

1 Answers1

-1

I would try to run any code as the certain user by impersonating the user.

Following the first answer from: Run Code as a different user I would do the following

static void Main(string[] args)
{
    var credentials = new UserCredentials("xxx", "yyy", "zzz");

    try
    {   
        using (var xyz = credentials.LogonUser(LogonType.Network))
        {
            // do whatever you want as this user.
            Console.WriteLine("Success");
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Fail");
    }
}

Note: the code looks different than, the one provided in the linked question because the API used is marked obsolete and you should write it like I did

Code uses the nuget package: https://www.nuget.org/packages/SimpleImpersonation

Seems to work on my end:

enter image description here

Rand Random
  • 7,300
  • 10
  • 40
  • 88
  • This still requires my application to handle the passwords in clear text which I am trying to avoid. – user3696412 Aug 04 '23 at 11:35
  • well the second your user inputs data it is clear text, just don't save the data anywhere – Rand Random Aug 04 '23 at 11:35
  • It's about not having the data in my applications memory. As I cited in my post, Microsoft recommends just not to have credentials in an application at all and using an external provider to handle them (such as windows authentication). I am just looking for a way to implement this in C#. – user3696412 Aug 04 '23 at 11:38
  • SecureString can help when dealing with passwords in memory. – Kevin Cook Aug 14 '23 at 11:41
  • @KevinCook - though SecureString should also be avoided – Rand Random Aug 14 '23 at 11:44