C# ActiveDirectory keeps returning false. Why? - c#

I know my Account Username and password. I am able to login to any PC on the domain.
Console.WriteLine("User Name: " + userName + " Password: " + tb.Text.ToString().Trim());
System.DirectoryServices.AccountManagement.PrincipalContext pc = new System.DirectoryServices.AccountManagement.PrincipalContext(ContextType.Domain, "DOMAIN.TLD");
// validate the credentials
bool validatedOnDomain = pc.ValidateCredentials(userName, tb.Text.ToString().Trim());
return validatedOnDomain;
This method keeps returning false.
Am I doing something wrong here? I also know what my password is. Any assitance would be great!
tb -> TextBox where the password is being inputted. I remove all white spaces and trimmed it (in case a user screws up)

Can you try this :
bool validatedOnDomain = pc.ValidateCredentials(userName, tb.Text.ToString().Trim(), ContextOptions.Negotiate);
You just have to Specifie the options that are used for binding to the server.

Related

BCrypt.Verify not working for c# asp.net web application

I am trying to verify a hashed password that is hashed in the register page, when I try to verify the hashed password with a entered password from the login, false is always returned.
I am hashing the password so:
string hashPassword = BCrypt.Net.BCrypt.HashPassword(Password);
The hashpassword is then saved to the database.
I try to verify the password so:
bool validPassword = BCrypt.Net.BCrypt.Verify(ProvidedPassword, StoredPassword);
Debug.WriteLine(validPassword);
if (validPassword)
{
Debug.WriteLine(ProvidedPassword + " is valid");
}
else
{
Debug.WriteLine("Passwords do not match");
}
I am using this source from github.
I have tried multiple methods and still always returns a false value.
I found the issue, my stored procedure parameters did not match my tables paremeters

Pass String Variable Into Nework Credential Constructor for Password Arguement

What I have is a function that allows a domain user to be authenticated against their LDAP credentials. However, it works long as I hard-code a known password as a raw string... which is a no-no, of course. I wish to pass in a string value received from a TextBox I have set up. Here is the function:
public static bool fnValLDAPCreds()
{
bool validation;
try
{
LdapConnection ADConn = new LdapConnection(new LdapDirectoryIdentifier((string)null, false, false));
NetworkCredential NetCred = new NetworkCredential(Environment.UserName, "Password123", Environment.UserDomainName);
ADConn.Credential = NetCred;
ADConn.AuthType = AuthType.Negotiate;
// the user's authenticated here; creds used to login on the domain controller.
ADConn.Bind(NetCred);
validation = true;
MessageBox.Show("You were successfully authenticated against AD using LDAP!");
}
catch (LdapException)
{
validation = false;
MessageBox.Show("Your login was unsuccesful. Try a different set of credentials.");
}
return validation;
}
What I've tried to do was substitute in a value from my TextBox, but since it lies in the static bool I have not been successful with making any external references to a control in the current context. I'm calling this function in button handler to fire it off. How can I swap in a string DomPassWord variable that gets its value from the textbox I have setup to obtain it?
NetworkCredential NetCred = new NetworkCredential(Environment.UserName, DomPassWord, Environment.UserDomainName); is what I'm striving for, as I can securely match a password in the domain with no hard-coding, using something like DomPassWord = txtUserPW.Text. Tried the SecureString route, but was unsuccessful in that regard as well. Any ideas?
You cannot access text boxes inside a static method, since they aren't static fields (at least it looks like it from what you've written).
But you can simply pass your arguments to your method. Change it to something like this:
public void ButtonClick(object sender, EventArgs args)
{
// bool valid = fnValLDAPCreds(Environment.UserName, "Password123", Environment.UserDomainName);
bool valid = fnValLDAPCreds(txtUserName.Text, txtUserPW.Text, Environment.UserDomainName);
}
public static bool fnValLDAPCreds(string username, string password, string domain)
{
try
{
LdapConnection ADConn = new LdapConnection(new LdapDirectoryIdentifier((string)null, false, false));
NetworkCredential NetCred = new NetworkCredential(username, password, domain);
ADConn.Credential = NetCred;
ADConn.AuthType = AuthType.Negotiate;
// the user's authenticated here; creds used to login on the domain controller.
ADConn.Bind(NetCred);
MessageBox.Show("You were successfully authenticated against AD using LDAP!");
return true;
}
catch (LdapException)
{
MessageBox.Show("Your login was unsuccesful. Try a different set of credentials.");
return false;
}
}
Kinda tangential, but have you thought about AuthType.Ntlm? If all you're doing this for is to make sure user 'Charlie' is actually Charlie by making him type in his password? Then you're on the right track. But if you're trying to connect in to AD using the current user credentials as a way of getting to AD itself? Then you might want to take a look at
ADConn.AuthType = AuthType.Ntlm;
... and letting windows handle this for you (no need to have the user type in a password at all - it'll use their current windows credentials.)

Edittext.Text shows right value but uses the wrong

i've searched in google and forum but didn't found anything about my strange problem. Sry for my bad english :)
It's really strange and difficult so i want to discribe it as simply as possible
User input in edittext (type: textPassword): 1 -> Logged in -> worked
var loginResult = await connection.LoginAsync(this.Username.Text, this.Password.Text, WebLoginType.User);
Password encrypted it in "2FYM9iWHHecf45vPjjZPfg=="
var newLogin = new LoginData
{
Username = this.Username.Text,
Password = Encrypter.Encrypt(this.Password.Text),
WebServiceAddress = this.WebServiceAddress.Text,
IsOnline = true,
IsActive = true,
License = this._license
};
Now on logout the password gets decrypted in "1" again, but in layout i can see it has more than one character in edittext. this.Edittext.Text = "1"
this.Password.SetText(Encrypter.Decrypt(setting.LastLoginPassword), TextView.BufferType.Normal);
If i login again i can see this.Edittext.Text is "1" but WebService says that it is the wrong password
Now if i delete the characters in edittext and write manually "1" it works.
What magic is going on?
Solved Probem: The Encrypter fills the rest of bytes with \u0000 until it gets its size of 16 bytes. I had to remove this with
return Encoding.UTF8.GetString(result, 0, result.Length).TrimEnd('\u0000');
Now it works.

Active Directory PrincipalContext.ValidateCredentials domain disambiguation

I'm dealing with two domains - one is a trusted domain. There may be a JohnSmith on one domain and another JohnSmith on the other. Both of these people need to log into my application.
My problem: it doesn't matter which domain I pass in - this code returns true! How do I know which JohnSmith is logging in?
static public bool CheckCredentials(
string userName, string password, string domain)
{
using (var context = new PrincipalContext(ContextType.Domain, domain))
{
return context.ValidateCredentials(userName, password);
}
}
The ValidateCredentials works with userPrincipalName you perhaps can try to build the first parameter (username) combining the login and the domain to create the username JohnSmith#dom1.com versus JohnSmith#dom2.com.
You can always retrieve the full DN of the user who has logged in using
UserPrincipal up = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, userName);
up.UserPrincipalName // shows user#domain.com
up.DistinguishedName // shows CN=Surname,OU=group,DC=domain,DC=com
up.SamAccountName // shows login name
Use the up.SamAccountName to subsequent calls to ValidateCredentials including the domain name - you can't have 2 users who log in using the same sAMAccountName after all!
The DistinguishedName will definitely show you which JohnSmith logged in.
Based on JPBlanc's answer, I've re-written my code. I've also added a try/catch in case a bogus domain is passed in.
static public bool CheckCredentials(
string userName, string password, string domain)
{
string userPrincipalName = userName + "#" + domain + ".com";
try
{
using (var context = new PrincipalContext(ContextType.Domain, domain))
{
return context.ValidateCredentials(userPrincipalName, password);
}
}
catch // a bogus domain causes an LDAP error
{
return false;
}
}
The accepted answer will fail with Domains that contain different email addresses within them. Example:
Domain = Company
User1 = employee#department1.com (under company Domain)
User2 = employee2#Department2.com (under company Domain)
The provided answer will return false using:
userName = "employee";
domain = "company";
string userPrincipalName = userName + "#" + domain + ".com";
The correct way to encompass users across domains is:
string userPrincipalName = userName + "#" + domain;
without the .com portion it searches the user AT that domain instead of searching for an email within a global domain.

Validating a user's credentials remotely

I currently use LogonUser() to authenticate my user's username and password on my local domain at the office and it works great for what i need it to do.
Since I developed the app I now need to make it work over my VPN. It seems LogonUser() will not work with REMOTELY validating credentials. Or will it? Is it possible to use LogonUser() to validate a user's credentials on a REMOTE domain account?
I have read in some places that using LOGON32_LOGON_NEW_CREDENTIALS for the 4th param (login type) and LOGON32_PROVIDER_WINNT50 for the 5th param (provider) would do the trick. But every time I try that I ALWAYS get success... I can supply a bogas user and pass and it will work every time :(.
Ideas?
Edit - Added Notes
Tried to use this function but I kept getting the exception telling me the user/pass was bad.
public bool Win2kCredentialsIsValid(string domain, string username, string password)
{
string adPath = "LDAP://" + domain + "/rootDSE";
DirectoryEntry adRoot = new DirectoryEntry(adPath, domain + "\\" + username, password, AuthenticationTypes.ReadonlyServer);
try
{
object o = adRoot.Properties["defaultNamingContext"];
}
catch
{
return false;
}
return true;
}
--
Edit - Added More Notes
OK so I tried yet another example just to get it to work and started down this path, and there are a few things to note...
MyServerHostName is exactly that, my server's hostname. EX: 'Server01'.
My domain name in this example is 'MyDomain.local'
So that makes my FQN for the server 'Server01.MyDomain.local'
I tried to make this work and got the following error...
The supplied context type does not match the server contacted. The server type is Domain.
This errored out at : var context = new PrincipalContext(ContextType.ApplicationDirectory, "MyServerHostName:389", "DC=MyDomain,DC=local"))
private bool CheckADCredentials()
{
bool bResults;
using (var context = new PrincipalContext(ContextType.ApplicationDirectory,
"MyServerHostName:389",
"DC=MyDomain,DC=local"))
{
var username = "firstname.lastname";
var email = "firstname.lastname#MyServerHostName";
var password = "123456";
var user = new UserPrincipal(context)
{
Name = username,
EmailAddress = email
};
user.SetPassword(password);
user.Save();
if (context.ValidateCredentials(username, password, ContextOptions.SimpleBind))
{
bResults = true;
}
else
{
bResults = false;
}
user.Dispose();
}
return bResults;
}
I ended up going with a different solution. Instead of trying to validate a user's account on a domain that my PC was not connected to I ended up caching my domain credentials in the database and just built a salted MD5 type encrypt function so it would make it hard .. er.. for someone to crack it. ;)
Now I just validate against cached credentials in the database when working remotely... It just required the user to first login on the domain but then the user can use it remotely day and night. ;)
Thanks!

Categories

Resources