Is it possible to enable (or disable) a user in Active Directory with LDAP command?
And also, is it possible doing it with C#?
I've already looked
here
and
here
Thanks,
J
using this reference Howto: (Almost) Everything In Active Directory via C#
you can use "userAccountControl" attribute to enable and disable
you need to pass DirectoryEntry to the function
Enable:
public static void Enable(DirectoryEntry user)
{
try
{
int val = (int)user.Properties["userAccountControl"].Value;
user.Properties["userAccountControl"].Value = val & ~0x2;
//ADS_UF_NORMAL_ACCOUNT;
user.CommitChanges();
user.Close();
}
catch (System.DirectoryServices.DirectoryServicesCOMException E)
{
//DoSomethingWith --> E.Message.ToString();
}
}
Disable :
public void Disable(DirectoryEntry user)
{
try
{
int val = (int)user.Properties["userAccountControl"].Value;
user.Properties["userAccountControl"].Value = val | 0x2;
//ADS_UF_ACCOUNTDISABLE;
user.CommitChanges();
user.Close();
}
catch (System.DirectoryServices.DirectoryServicesCOMException E)
{
//DoSomethingWith --> E.Message.ToString();
}
}
Using: Morgan Tech Space as Reference:
Enable Active Directory User Account via userAccountControl using C#
private static void EnableADUserUsingUserAccountControl(string username)
{
try
{
DirectoryEntry domainEntry = Domain.GetCurrentDomain().GetDirectoryEntry();
// ldap filter
string searchFilter = string.Format(#"(&(objectCategory=person)(objectClass=user)
(!sAMAccountType=805306370)(|(userPrincipalName={0})(sAMAccountName={0})))", username);
DirectorySearcher searcher = new DirectorySearcher(domainEntry, searchFilter);
SearchResult searchResult = searcher.FindOne();
if (searcher != null)
{
DirectoryEntry userEntry = searchResult.GetDirectoryEntry();
int old_UAC=(int)userEntry.Properties["userAccountControl"][0];
// AD user account disable flag
int ADS_UF_ACCOUNTDISABLE = 2;
// To enable an ad user account, we need to clear the disable bit/flag:
userEntry.Properties["userAccountControl"][0] = (old_UAC & ~ADS_UF_ACCOUNTDISABLE);
userEntry.CommitChanges();
Console.WriteLine("Active Director User Account Enabled successfully
through userAccountControl property");
}
else
{
//AD User Not Found
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Disable Active Directory User Account via userAccountControl using C#
private static void DisableADUserUsingUserAccountControl(string username)
{
try
{
DirectoryEntry domainEntry = Domain.GetCurrentDomain().GetDirectoryEntry();
// ldap filter
string searchFilter = string.Format(#"(&(objectCategory=person)(objectClass=user)
(!sAMAccountType=805306370)(|(userPrincipalName={0})(sAMAccountName={0})))", username);
DirectorySearcher searcher = new DirectorySearcher(domainEntry, searchFilter);
SearchResult searchResult = searcher.FindOne();
if (searcher != null)
{
DirectoryEntry userEntry = searchResult.GetDirectoryEntry();
int old_UAC = (int)userEntry.Properties["userAccountControl"][0];
// AD user account disable flag
int ADS_UF_ACCOUNTDISABLE = 2;
// To disable an ad user account, we need to set the disable bit/flag:
userEntry.Properties["userAccountControl"][0] = (old_UAC | ADS_UF_ACCOUNTDISABLE);
userEntry.CommitChanges();
Console.WriteLine("Active Director User Account Disabled successfully
through userAccountControl property");
}
else
{
//AD User Not Found
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Enable AD User Account via UserPrincipal using C#
private static void EnableADUserUsingUserPrincipal(string username)
{
try
{
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain);
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity
(principalContext, username);
userPrincipal.Enabled = true;
userPrincipal.Save();
Console.WriteLine("Active Director User Account Enabled successfully through UserPrincipal");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Disable AD User Account via UserPrincipal using C#
private static void DiableADUserUsingUserPrincipal(string username)
{
try
{
// To use this class, you need add reference System.DirectoryServices.AccountManagement which
is available only from .NET 3.5;
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain);
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity
(principalContext, username);
userPrincipal.Enabled = false;
userPrincipal.Save();
Console.WriteLine("Active Director User Account Disabled successfully through UserPrincipal");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
You can use PrincipalContext to enable/ disable AD account.
To Enable the AD you can do something like this:
private static void EnableADUserUsingUserPrincipal(string username)
{
try
{
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain);
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity
(principalContext, username);
userPrincipal.Enabled = true;
userPrincipal.Save();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
To disable Active Directory you can just set the userPrincipal.Enabled = false;
Related
NO asp.net c# used
I need to know if user is login once he/she enter a form and if he/she is not login, he goes back to the login form. Everywhere I saw people use asp.net to achieve that but I want to know how to do it without using asp.net.
public DataTable Login(String Username, String Password)
{
server = "localhost";
database = "xxxx";
uid = "root";
password = "";
string MySQLConnectionString = $"datasource=127.0.0.1;port = 3306; SERVER={server}; DATABASE={database}; USERNAME={uid}; PASSWORD={password};sslmode=none";
MySqlConnection db_Conn = new MySqlConnection(MySQLConnectionString);
MySqlCommand cmd = new MySqlCommand();
db_Conn.ConnectionString = MySQLConnectionString;
string username_txtfield = username_txtbox.Text;
string pw_txtfield = password_txtbox.Text;
try
{
db_Conn.Open();
cmd.Connection = db_Conn;
cmd.CommandText = "SELECT count(*),user_id,person_username,role_id FROM user_tb " +
"WHERE person_username=#username " +
"AND user_password=#password";
cmd.Prepare();
cmd.Parameters.AddWithValue("#username", username_txtfield);
cmd.Parameters.AddWithValue("#password", pw_txtfield);
MySqlDataReader dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
db_Conn.Close();
return dt;
}
catch (Exception ex)
{
throw ex;
}
}
login btn in my login form
private void button1_Click(object sender, EventArgs e)
{
//login();
try
{
DataTable result = Login(username_txtbox.Text, password_txtbox.Text);
if (result.Rows.Count == 1)
{
this.Hide();
string role = result.Rows[0]["role_id"].ToString();
switch (role)
{
case "3":
MessageBox.Show("User login successfully!");
user_form_page();
break;
case "1":
MessageBox.Show("Admin login successfully!");
//this.Hide();
Admin_page admin_form = new Admin_page();
admin_form.ShowDialog();
this.Close();
break;
}
}
else
{
MessageBox.Show("INVALID USERNAME OR PASSWORD");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Of course the ASP.Net identity services is a mature way of doing such a task but if you want you can have your own method of authentication but, you will need to implement many things.
Many of the stuff you need is actually based on the scenario you are implementing but the most basic thing you need is a static user that will be used via your methods to see if the user is already logged in or not. For example you can have:
public static class Authentication
{
public static User CurrentUser { get; private set; }
public static bool Login(User user)
{
if(user == null)
throw new ArgumentException("Invalid user","user");
CurrentUser = user;
}
}
This is just the most basic implementation of such a thing you can then check if CurrentUser is null or not and direct user to login page or show her the results.
As your requirements grow you will need to implement more stuff. A logout, a local or remote database for users, store currently logged in user in disk so that she doesn't need to login again after closing the app and many other things
Edit
Based on your new information you can add this line to your login button click like this:
if (result.Rows.Count == 1)
{
Authentication.Login(new User(result.Rows[0]["username"],result.Rows[0]["role_id"])
//The rest of code
}
I have also presumed that you have a class like:
class User
{
public string Name { get; }
public int RoleId { get; }
public User(string name, int roleId)
{
Name = name;
RoleId = roleId;
}
}
And then you have to check Authentication.CurrentUser against null in your user form or admin form constructors to ensure user is login you can use the information in Authentication.CurrentUser to show logged in user name or role or any other info.
I hope this helps you. If you need more info please say so.
I am writing a method to determine if a user exists in an Active Directory Group. I may not know this user's password but I do have another username/password in this Active Directory Group. Is there a more efficient way to do this? Setting the SamAccountName property and the call to userFound.GetGroups() seems to be bottlenecks.
Any suggestions are appreciated.
try
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, ipaddress, remoteDomainAndUserName, password))
{
UserPrincipal qbeUser = new UserPrincipal(pc);
try
{
qbeUser.SamAccountName = lookUpUserName; // don't know password of this user
aDResult = ADResult.Valid; // right now remoteDomainAndUserName/password is valid on the domain, don't know if lookUpUserName is a valid user yet
}
catch (Exception e)
{
return ADResult.InvalidNonLookupID;
}
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
foreach (var found in srch.FindAll())
{
UserPrincipal userFound = found as UserPrincipal;
if (userFound != null)
{
foreach (Principal p in userFound.GetGroups())
{
if (p.SamAccountName.ToLower().Trim() == groupName)
{
bool isEnabled = true;
if (userFound.Enabled.HasValue)
{
isEnabled = userFound.Enabled.Value;
}
if (isEnabled)
return ADResult.ValidInGroup;
else
return ADResult.DisabledInGroup;
}
else
aDResult = ADResult.InvalidInGroup;
}
}
}
}
}
catch (PrincipalServerDownException e)
{
// cannot connect to AD
aDResult = ADResult.Offline;
}
catch (LdapException e)
{
// cannot connect to AD
aDResult = ADResult.Offline;
}
catch (Exception e)
{
// cannot connect to AD
aDResult = ADResult.Offline;
}
//This is a method I use in a WCF web service I created
//userName is the sAMAccount name of the user
//groupName is the AD group
public bool IsMemberOfGroup(string groupName, string userName)
{
try
{
PrincipalContext context = new PrincipalContext(ContextType.Domain);
UserPrincipal user = UserPrincipal.FindByIdentity(context, userName);
GroupPrincipal group = GroupPrincipal.FindByIdentity(context, groupName);
if (group == null)
return false;
if (user != null)
return group.Members.Contains(user);
}
catch (System.Exception ex)
{
//Log exception
}
return false;
}
I trying to implement LDAP authentication in C# Web Application.
I tried is using the below code.
try
{
using (LdapConnection conn = new LdapConnection(this.Server))
{
string uname = userName;
if (!string.IsNullOrEmpty(this.UsernamePrepend))
{
uname = string.Concat(this.UsernamePrepend, userName);
}
NetworkCredential cred = new NetworkCredential(uname, password, null);
conn.SessionOptions.SecureSocketLayer = true;
conn.SessionOptions.VerifyServerCertificate = (LdapConnection con, X509Certificate cer) => true;
conn.SessionOptions.ProtocolVersion = 3;
conn.AuthType = AuthType.Basic;
conn.Bind(cred);
}
}
catch (LdapException ldapException)
{
LdapException ex = ldapException;
if (!ex.ErrorCode.Equals(49))
{
this.LogError(ex, userName);
throw ex;
}
}
flag = true;
Every time I run it, it goes into catch block with exception LDAP server is unavailable.
Am I missing something?
Remove conn.SessionOptions.SecureSocketLayer = true; from your code
My login window uses LDAP to authenticate users. However, when validating, it always returns false.
Here is the code for validation which I got from CodeProject:
public bool fnValidateUser()
{
bool validation;
try
{
LdapConnection lcon = new LdapConnection
(new LdapDirectoryIdentifier((string)null, false, false));
NetworkCredential nc = new NetworkCredential(Environment.UserName,
txtPassword.SecurePassword, Environment.UserDomainName);
lcon.Credential = nc;
lcon.AuthType = AuthType.Negotiate;
// user has authenticated at this point,
// as the credentials were used to login to the dc.
lcon.Bind(nc);
validation = true;
}
catch (LdapException)
{
validation = false;
}
return validation;
}
txtPassword.SecurePassword is the PasswordBox. When I enter my password/pin and hit login, it displays the MessageBox for whenever validation is false.
What am I doing wrong?
UPDATE: The exception indicates "The LDAP Server is Unavailable", at this line lcon.Bind(nc);
You can try this sample piece of code.
// the username and password to authenticate
const string domain = "OU=Organization,DC=mydomain,DC=com";
string password = "mypass";
string userName = "myuser";
// define your connection
LdapConnection ldapConnection = new LdapConnection("ldap.mydomain.com:389");
try
{
// authenticate the username and password
using (ldapConnection)
{
// pass in the network creds, and the domain.
var networkCredential = new NetworkCredential(username, password, domain);
// if we're using unsecured port 389, set to false. If using port 636, set this to true.
ldapConnection.SessionOptions.SecureSocketLayer = false;
// since this is an internal application, just accept the certificate either way
ldapConnection.SessionOptions.VerifyServerCertificate += delegate { return true; };
// to force NTLM\Kerberos use AuthType.Negotiate, for non-TLS and unsecured, just use AuthType.Basic
ldapConnection.AuthType = AuthType.Basic;
// authenticate the user
ldapConnection.Bind(networkCredential);
}
catch (LdapException ldapException)
{
//Authentication failed, exception will dictate why
}
}
I went ahead and found another approach for this, without using LDAP.
PrincipalContext adContext = new PrincipalContext(ContextType.Machine);
private async void btnLogin_Click(object sender, RoutedEventArgs e)
{
try
{
using (adContext)
{
if (adContext.ValidateCredentials(txtUsername.Text, txtPassword.Password))
{
MainWindow main = new MainWindow();
main.Show();
main.txtLoggedInUser.Text = UserPrincipal.Current.DisplayName;
this.Close();
}
else
{
MessageBox.Show("Incorrect Username or Password!");
}
}
}
catch(Exception ex)
{
var exceptionDialog = new MessageDialog
{
Message = { Text = ex.ToString() }
};
await DialogHost.Show(exceptionDialog, "RootDialog");
}
}
I am getting the following error while connecting using LDAP
Connection.freeWriteSemaphore(-2): semaphore not owned by any thread
I am using the following code
public static bool Authenticate(string userName, string password)
{
//logger.Debug("Try to connect to LDAP to authenticate user with " + userName + "/***");
string uDN = ldapUserDN.Replace("$UID", userName);
bool flag = false;
LdapConnection ldapConn = new LdapConnection();
try
{
ldapConn.Connect(ldapServer, int.Parse(ldapServerPort));
ldapConn.Bind(uDN, password);
flag = ldapConn.Bound;
}
catch (Exception ex)
{
//logger.Error("Exception in Authenticate():", ex);
}
finally
{
ldapConn.Disconnect();
}
return flag;
}