8

In C#, how do I authenticate a user on a network machine? For example, I want to authenticate the user testuser with password testpassword on the machine EXAMPLEMACHINE from a different machine which is network-connected to EXAMPLEMACHINE. For example, I am on MYMACHINE and I want to authenticate testuser with testpassword on EXAMPLEMACHINE.

I have tried the following but it keeps telling me that, The LDAP server is unavailable:

PrincipalContext context =
    new PrincipalContext(ContextType.Domain, exampleMachineDomain);
return context.ValidateCredentials(username, password);
Alexandru
  • 12,264
  • 17
  • 113
  • 208
  • 1
    have you verified that the connect string to get to the ldap server is working? Are you using directoryservices or doing this with the windows authentication mode in the app config or web config file? – Brian Jan 23 '12 at 14:59
  • 1
    Is EXAMPLEMACHINE a domain controller? If it isn't, that may be your problem. I don't know if you can validate credentials on a regular (i.e. non-server) machine just because it's visible on the network. That's what the error message is telling you, I think. – qxn Jan 23 '12 at 15:04
  • That is the problem. I don't have a domain controller. I want to validate credentials on a regular machine, just because it is visible on the network. – Alexandru Jan 23 '12 at 15:07

4 Answers4

2

If your machines are not in a domain, you need to use ContextType.Machine:

PrincipalContext context = 
    new PrincipalContext(ContextType.Machine, exampleMachineDomain);
return context.ValidateCredentials(username, password);
Alexandru
  • 12,264
  • 17
  • 113
  • 208
Christoph Fink
  • 22,727
  • 9
  • 68
  • 113
2

If you are not using Active Directory, you could use something like this:

using System.Security;
using System.DirectoryServices.AccountManagement;
    public struct Credentials
    {
        public string Username;
        public string Password;
    }
    public class Domain_Authentication
    {
        public Credentials Credentials;
        public string Domain;
        public Domain_Authentication(string Username, string Password, string SDomain)
        {
            Credentials.Username = Username;
            Credentials.Password = Password;
            Domain = SDomain;
        }
        public bool IsValid()
        {
            using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, Domain))
            {
                // validate the credentials
                return pc.ValidateCredentials(Credentials.Username, Credentials.Password);
            }
        }
    }

If you are using Active Directory, you could use something like this:

 PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

    // define a "query-by-example" principal - here, we search for a UserPrincipal 
    UserPrincipal qbeUser = new UserPrincipal(ctx);

    // if you're looking for a particular user - you can limit the search by specifying
    // e.g. a SAMAccountName, a first name - whatever criteria you are looking for
    qbeUser.SamAccountName = "johndoe";

    // create your principal searcher passing in the QBE principal    
    PrincipalSearcher srch = new PrincipalSearcher(qbeUser);

    // find all matches
    foreach(var found in srch.FindAll())
    {
        // do whatever here - "found" is of type "Principal" - it could be user, group, computer.....          
    }
Alexandru
  • 12,264
  • 17
  • 113
  • 208
MethodMan
  • 18,625
  • 6
  • 34
  • 52
  • 1
    I do not understand these examples... It says to use ValidateCredentials() when not under AD, and a regular search if it IS under AD - and the AD code doesn't even mention the user's password. What does this really accomplish? – Oskar Berggren Jun 23 '16 at 14:20
  • Perhaps you need to understand `PrincipalContext` before you comment on something you should understand it's context. why write all kinds of code using AD when PrincipalContext gives you more robust functionality / access.. – MethodMan Jun 23 '16 at 15:43
  • As I tried to imply... I'm trying to understand. Do you mean that the first example ("not using AD") is when you have a pre-AD windows domain? Or why does it work with ContextType.Domain specified if there is no AD domain? And in the second example ("using AD"), where/how does it actually verify the user? (i.e corresponding to username/password from the first example). – Oskar Berggren Jun 23 '16 at 16:22
  • this works and you do not have to specify a specific domain perhaps you should try the example and change it to fit your use case.. the code is pretty straight forward. – MethodMan Jun 23 '16 at 16:25
1

There's a few different options presented in this answer. The snippet you pasted above should work, though.

Community
  • 1
  • 1
Joel Martinez
  • 46,929
  • 26
  • 130
  • 185
1

The best way to do this would be to use WNetUseConnection, a Win32 API which allows for the most direct way. In effect, you're trying to call

net use \\server password /user:myUserName,

which is what this API is intended to do.

A good example of this has been answered at this question.

Because the PinvokeWindowsNetworking function returns null when successful, the simplest authentication code is

private static bool AuthenticateUserOnRemote(string server, string userName, string password)
{
    var connected = PinvokeWindowsNetworking.connectToRemote(server, userName, password);
    var disconnected = PinvokeWindowsNetworking.disconnectRemote(server);
    return connected == null;
}
Community
  • 1
  • 1
Barracoder
  • 3,696
  • 2
  • 28
  • 31