PrincipalContext.ValidateCredentials: find username or password is invalid - c#

I am using AD authentication in my application:
bool _isValid;
using (var pc = new PrincipalContext(ContextType.Domain, DomainPath))
{
isValid = pc.ValidateCredentials(username, password, ContextOptions.Negotiate);
}
Is there any way to find out if I am getting isValid set to false because of an invalid username or an invalid password?

You can't be sure directly which one is invalid. But you can try to retrieve the user from active directory to determine which one is wrong after false validation like this;
bool _isValid;
using (var pc = new PrincipalContext(ContextType.Domain, DomainPath))
{
isValid = pc.ValidateCredentials(username, password, ContextOptions.Negotiate);
if (!isValid)
{
var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, username);
if (user == null)
{
//User doesn't exist
}
else
{
//Password is invalid
}
}
}

Related

LDAP change/reset password c# mvc

I tried to change/reset password to user that has to change his password after first login using c#
My code:
var domain = WebConfigurationManager.AppSettings["ONLINE-AD"];
directoryEntry.Username = userName;
directoryEntry.Password = password;
var directorySearcher = new DirectorySearcher(directoryEntry);
SearchResult result = directorySearcher.FindOne();
if (result != null)
{
DirectoryEntry userEntry = result.GetDirectoryEntry();
if (userEntry != null)
{
userEntry.Invoke("SetPassword", model.Resetpassword);
userEntry.CommitChanges();
}
}
But when I tried to do FindOne() i got an error 773 (means that the user has to change password for first time)
here is the error :
How to access user using LDAP ?(I successed to do login with
proper user)
I created Admin user that can manage all users then I got all users using the admin and find the wanted user and set password to this user:
public string ResetPassword(LoginDTO model) {
try {
//get context by admin user
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, WebConfigurationManager.AppSettings["ONLINE-AD"], WebConfigurationManager.AppSettings["AdminName"], WebConfigurationManager.AppSettings["AdminPassword"]);
//find the wanted user
var user = UserPrincipal.FindByIdentity(ctx, model.UserName);
if (user != null) {
try {
user.ChangePassword(model.Password, model.NewPassword);
} catch {
return "-1";
}
}
} catch (Exception ex) {
return "-1";
}
return "1"
}

Find if user belongs to group

I want to find if the user belongs to an AD group. Can you advise how I can add that functionality using the following code?
I ask the user to enter their username and password (through a form), so not using the windows credentials. With the below code I am able to validate the user, by passing the username, and password. How can I build on the code to check if user exists in the AD Group. Is there another way to do this? Please advice
DirectoryEntry adsEntry = new DirectoryEntry("domain", userid, password);
DirectorySearcher adsSearcher = new DirectorySearcher(adsEntry);
try {
SearchResult adsSearchResult = adsSearcher.FindOne();
context.Session.Timeout = 2;
context.Session["ValidatedLoginID"] = userid;
user.Verified = true;
adsEntry.Close();
} catch ( Exception ex ) {
// Failed to authenticate. Most likely it is caused by unknown user
// id or bad strPassword.
user.error = ex.Message;
adsEntry.Close();
}
You can use the below code:
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "DOMAINNAME");
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName");
// find the group in question
GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, "YourGroupNameHere");
if(user != null)
{
// check if user is member of that group
if (user.IsMemberOf(group))
{
// do something.....
}
}
Also look at: How to check if a user belongs to an AD group?
Here is how I solved this :
DirectoryEntry adsEntry = new DirectoryEntry("domain", userid, password);
DirectorySearcher adsSearcher = new DirectorySearcher(adsEntry);
adsSearcher.Filter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName=" + userid + "))";
try
{
SearchResult adsSearchResult = adsSearcher.FindOne();
string propertyName = "memberOf";
ResultPropertyValueCollection rpvcResult = adsSearchResult.Properties[propertyName];
foreach (Object PropertyValue in rpvcResult)
{
if (PropertyValue.ToString() == "Group Name")
{
user.Verified = true;
user.FullName = GetFullName(userid);
adsEntry.Close();
} else
{
user.Verified = false;
user.error = "You do not belong to the Group so you cannot do this function";
}
}
} catch (Exception ex)
{
user.error = "Please check your username and password credentials";
adsEntry.Close();
}

Why won't this search by OU?

I am trying to validate a user's login credentials based on their organizational unit in Active Directory. How can I do this?
This is my attempt so far, but I can't get it to specify by OU.
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain,
"domain", "OU=LRF,OU=HR,OU=Users, DC=domain, DC=local"))
{
// validate the credentials
bool isValid = pc.ValidateCredentials(textBox1.Text, textBox2.Text);
if (isValid == true)
{
new Form1().Show();
}
else MessageBox.Show("Access Denied");
}

How the PrincipalContext works

I need to let users bind there accounts to the Active Directory. This means that admin needs a GUI where he/she can write a Active Directory account like this : MyDomain\MyName and then get a validation if the users exists before save.
Im using this code to validate the name :
public static bool CheckActiveDirectoryAccount(string account)
{
string ADServer = null;
string ADDomain = null;
string ADUserName = null;
string ADUserPassword = null;
SetADSettings(out ADServer, out ADDomain, out ADUserName, out ADUserPassword);
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, ADServer, ADUserName, ADUserPassword))
{
using (UserPrincipal user = UserPrincipal.FindByIdentity(context, account))
{
if(user != null)
return true;
else
return false;
}
}
}
The problem with this code is that there seems to be no way to check the user for a specific domain? Instead I have to input the server, if I try to input the domain instead there will be exception(Server not found).
How do I let the admin enter domain and username of a AD account and then check it against the AD?
I am able to pass the domain into the principalcontext without issue, I'm not passing in the server. I would expect this to work for you.
public static bool CheckActiveDirectoryAccount(string account, string domain)
{
using (var pc = new PrincipalContext(ContextType.Domain, domain))
{
// Find a user
UserPrincipal user = UserPrincipal.FindByIdentity(pc, account);
if (user == null)
return false;
return true;
}
}
I have noticed poor performance when passing in the NetBIOS domain name, though it does work. As a result I pass in the DNS domain name whenever possible.
I ended up with this :
public static string CheckActiveDirectoryAccount(string account)
{
UserPrincipal user;
PrincipalContext context;
List<string> userPrincipalNameList;
string ADServer = null;
string ADUserName = null;
string ADUserPassword = null;
string userAccount;
account = account.ToLower();
GetADSettings(out ADServer, out ADUserName, out ADUserPassword);
if (ADUserName.Length > 0)
context = new PrincipalContext(ContextType.Domain, ADServer, null, ADUserName, ADUserPassword);
else
context = new PrincipalContext(ContextType.Domain, ADServer);
using (context)
{
if((user = UserPrincipal.FindByIdentity(context, account)) == null)
{
if(account.Contains("\\"))
{
userPrincipalNameList = user.UserPrincipalName.Split('\\').ToList();
if (userPrincipalNameList.Count > 0)
user = UserPrincipal.FindByIdentity(context, userPrincipalNameList[0]);
}
}
if (user != null)
{
using (user)
{
userPrincipalNameList = user.UserPrincipalName.Split('#').ToList();
userAccount = userPrincipalNameList.First();
if (userPrincipalNameList.Count > 1)
userAccount = userPrincipalNameList.Last() + "\\" + userAccount;
if (user != null)
return userAccount.ToLower();
}
}
}
return string.Empty;
}

Timeout issue When Using Active Directory

I'm trying to do a couple of things. First off this c# program verifies against Active Directory user credentials using:
var ADentry = new DirectoryEntry("LDAP://domain", uname, pword);
But obviously you need to pass in the username and password somehow. Is there a way that you can retrieve it automatically when the user signs in on the network from Active Directory and use that in the fields without having the username type in the username and password.
If not, I made it so the user can type in their credentials in the console. But if it doesn't work it ends up hanging forever. What type of code can I use to timeout after say 1 minute if this keeps hanging otherwise it hangs forever? thanks
I was trying to do an LDAP query and the following will do it for you. Most of it are methods but you may be interested in this line of code: PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, sDomain, sDefaultOU, ContextOptions.Negotiate);
The full code is here:
IsUserGroupMember("username", "group name the user is in");
public string sDomain = "your.domainName.com"
public string sDefaultOU = OU=**,OU=**,DC=**,DC=**,DC=**
public void IsUserGroupMember(string sUserName, string sGroupName)
{
try
{
UserPrincipal oUserPrincipal = GetUser(sUserName);
GroupPrincipal oGroupPrincipal = GetGroup(sGroupName);
if (oUserPrincipal != null && oGroupPrincipal != null)
{
//do something
}
else
{
//nothing
}
}
catch (PrincipalServerDownException)
{
throw;
}
catch (Exception)
{
throw;
}
}
public UserPrincipal GetUser(String sUserName)
{
PrincipalContext oPrincipalContext = GetPrincipalContext();
UserPrincipal oUserPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext, sUserName);
return oUserPrincipal;
}
public GroupPrincipal GetGroup(string sGroupName)
{
PrincipalContext oPrincipalContext = GetPrincipalContext();
GroupPrincipal oGroupPrincipal = GroupPrincipal.FindByIdentity(oPrincipalContext, sGroupName);
return oGroupPrincipal;
}
public PrincipalContext GetPrincipalContext()
{
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, sDomain, sDefaultOU, ContextOptions.Negotiate);
return oPrincipalContext;
}
I hope this code will be of use for you.

Categories

Resources