How to create new user account without password - c#

I would like to programmatically add new local user to a computer. I found the code here.
But I would like that the user could login without password. I saw that there is an option UserPrincipal.PasswordNotRequired=true but if I don't use SetPassword() it throws me an exception:
The password does not meet the password policy requirements...
Is it possible to make a new user with no password?
EDIT: the current code, which adds a new user successfully, but I have to provide some password.It is a complete copy from the link provided:
PrincipalContext oPrincipalContext = GetPrincipalContext();
UserPrincipal oUserPrincipal = new UserPrincipal(oPrincipalContext);
oUserPrincipal.Name = sUserName;
oUserPrincipal.SetPassword(sPassword);
oUserPrincipal.DisplayName = windowsUsername.Text;
oUserPrincipal.PasswordNeverExpires = true;
oUserPrincipal.PasswordNotRequired = true;
oUserPrincipal.Save();
GroupPrincipal usersGroup = GroupPrincipal.FindByIdentity(oPrincipalContext, "Users");
usersGroup.Members.Add(oUserPrincipal);
usersGroup.Save();

There are two potential reasons why your code isnt working.
Youre not running as admin
Your machine is on a domain with a group policy preventing what you want to do.
The code below has been tested on my machine and is working.
void Main()
{
PrincipalContext oPrincipalContext = GetPrincipalContext();
UserPrincipal oUserPrincipal = new UserPrincipal(oPrincipalContext);
oUserPrincipal.Name = "TestUser";
oUserPrincipal.SetPassword("");
oUserPrincipal.DisplayName = "TestUser";
oUserPrincipal.PasswordNeverExpires = true;
oUserPrincipal.PasswordNotRequired = true;
oUserPrincipal.Save();
GroupPrincipal usersGroup = GroupPrincipal.FindByIdentity(oPrincipalContext, "Users");
usersGroup.Members.Add(oUserPrincipal);
usersGroup.Save();
}
PrincipalContext GetPrincipalContext()
{
var dc = new PrincipalContext(ContextType.Machine);
return dc;
}
Things for you to try,
1. Try it on a machine that is not on your domain.
2. Try it on a machine that does not have any group policies applied.
3. Run your app as admin on the machine that you're having the issue with

Related

Why is User.Invoke("SetPassword") using my computer's current credentials and how I can I specify them instead?

I am able to create new users in a remote ActiveDirectory server, which I am doing using an admin account on that server. This is how I do that:
String connection = "LDAP://serveraddress/OU=NewUsers,OU=People,DC=mydomain,DC=local";
usersDirectoryEntry = new DirectoryEntry(connection, "adminUserName","adminPass");
DirectoryEntry newUser = usersDirectoryEntry.Children.Add(userString, "user");
newUser.CommitChanges();
However, immediately after I am trying to set the password using:
UpdatePassword(newUser, "userPasswordMeetsRequirements");
where
private static void UpdatePassword(DirectoryEntry User, String password)
{
User.Properties["pwdLastSet"].Value = -1;
User.Invoke("SetPassword", new object[] { password.Trim() });
User.Properties["userAccountControl"].Value = 0x0200 | 0x10000;
User.CommitChanges();
}
Where User is of type DirectoryEntry (https://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry(v=vs.110).aspx)
And on the User.Invoke line I get a System.Reflection.TargetInvocationException --> System.UnauthorizedAccessException: Access is denied.
That admin user should indeed have set password permissions. After looking in the AD logs I found that at the User.Invoke line my program was trying to connect to the AD server using my current credentials on my computer (which is on a different domain).
Why is this happening, and how can I force it to just use the admin account that it used for user creation?
Are you passing that newUser object to UpdatePassword? I would assume it's using the same credentials.
But if not, you can create a new object like this:
var user = new DirectoryEntry(newUser.Path, "adminUserName","adminPass");
UpdatePassword(user, somepassword);
Begining on .NET 3.5 and newer, you can use the System.DirectoryServices.AccountManagement
You can find information about it in System.DirectoryServices.AccountManagement Namespace.
Why don't you try the following :
PrincipalContext context = new PrincipalContext( ContextType.Domain, null, adAdminLogin, adAdminPassword );
UserPrincipal user = UserPrincipal.FindByIdentity( context, adUserLogin );
user.SetPassword( adUserNewPassword );
I'm able swicth to 3 diff domain using this (just changing domain LDAP path)
i don't see why you couldn't.
Domain = "LDAP://domain2.com";
ADUSER = MySuperAdmin;
ADpassword = "123";
DirectoryEntry Entry = new DirectoryEntry(Domain, ADUSER, ADpassword);
DirectoryEntry Entry = new DirectoryEntry(Domain, ADUSER, ADpassword);
DirectorySearcher Search = new DirectorySearcher(Entry);
Search.Filter = string.Format("(&(objectCategory=computer)(cn={0}))", HostName);
SearchResult Result = Search.FindOne();
now check if your are able find a device on your targeted domain
if it work try change the password if you not able it have nothing to do with the C# code but more with "MySuperAdmin" rigth on the domain2 .try direct in mmc you should pop the same error than in your application.
maybee a checkbox "User cannot change password" may cause the fail too

How to set connection time out when establishing context - PrincipalContext

using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, Domain, UserName, Password))
{
UserPrincipal U = new UserPrincipal(ctx);
U.GivenName = strFirstName;
U.Surname = strLastName;
U.EmailAddress = strEmail;
PrincipalSearcher srch = new PrincipalSearcher(U);
foreach (var principal in srch.FindAll())
{
var p = (UserPrincipal)principal;
if (!User.Any(x => x.Email == p.EmailAddress))
{
MyUserDataset.UserRow User = User.NewUserRow();
User.FirstName = p.GivenName;
User.LastName = p.Surname;
User.UserName = p.SamAccountName;
User.Email = p.EmailAddress;
User.AddUserRow(User);
}
}
User.AcceptChanges();
}
I'm using the PrincipalContext class above to establish a connection to the target directory and specify credentials for performing operations against the directory.
Does any one know how i can also specify the connection time out in the PrincipalContext Constructor?, i'm running into connection time out issues & i was wondering if i can control after how long the connection can time out.
Well, I guess the answer is no unfortunately. I have dig into the source code of PrincipalContext, it used DirectoryEntry which used unsafe native method System.DirectoryServices.Interop.UnsafeNativeMethods.ADsOpenObject to open LDAP connection.
As per this blog How to specify TimeOut for ldap bind in .Net, there is no way to configure the timeout on ADsOpenObject. However, it also mentioned that if using LdapConnection directly, then it is possible to set the timeout. In that case, you may not be able to user PrincipalContext.

Programmatically set up user account for custom identity application pool in IIS 7

In my C# code I need to create a custom identity for my web application and add it to IIS 7. I do the following:
string strAppPoolName = "MyAppPool";
string strUserName = Environment.UserDomainName + "\\" + "myappusername";
addUserAccount(strUserName, strUserPass);
using (ServerManager serverManager = new ServerManager())
{
//Add application pool
ApplicationPool appPool = serverManager.ApplicationPools.Add(strAppPoolName);
appPool.AutoStart = true;
appPool.ManagedPipelineMode = ManagedPipelineMode.Integrated;
appPool.ManagedRuntimeVersion = "v4.0";
appPool.ProcessModel.MaxProcesses = 1;
//Assign identity to a custom user account
appPool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser;
appPool.ProcessModel.UserName = strUserName;
appPool.ProcessModel.Password = strUserPass;
}
Where the user is added to the Active Directory as such:
public static void addUserAccount(string sUserName, string sPassword)
{
using (PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain))
{
using (UserPrincipal up = new UserPrincipal(oPrincipalContext))
{
up.SamAccountName = sUserName;
up.SetPassword(sPassword);
up.Enabled = true;
up.PasswordNeverExpires = true;
up.Description = "My app's user account";
up.Save();
}
}
}
The issue is that when I later add my site and application to IIS 7 under that application pool, the web application cannot run because it does not have sufficient permissions. More importantly for me, some of the .NET classes, such as System.Security.Cryptography fail with unexpected error codes even if I manually set read/write permissions for this new user account to the file system folder where my web app is installed.
So while doing a research I found the following statement:
If you use a custom identity, make sure that the user account you
specify is a member of the IIS_IUSRS group on the Web server so that
the account has proper access to resources. Additionally, when you use
Windows and Kerberos authentication in your environment, you might
need to register a Service Principle Name (SPN) with the domain
controller (DC).
So, how do you do this?
If you need to add that account to the IIS_IUSERS group, (which is local on the machine) you can use the GroupPrincipal for that. Keep in mind to create a PrincipalContext that is local for your machine, instead of the Domain one you used for the user. You can simply find the group by identity and then add the new created user to the Memberscollection. The Add method has an overload that accepts an UserPrincipal.
Your code would like this:
using (PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain))
{
using (PrincipalContext oGroupContext = new PrincipalContext(ContextType.Machine))
{
// find the local group IIS_IUSRS
using(var gp = GroupPrincipal.FindByIdentity(oGroupContext,"IIS_IUSRS"))
{
using (UserPrincipal up = new UserPrincipal(oPrincipalContext))
{
up.SamAccountName = sUserName;
up.SetPassword(sPassword);
up.Enabled = true;
up.PasswordNeverExpires = true;
up.Description = "My app's user account";
up.Save();
// add new user to Members of group
gp.Members.Add(up);
// save before Disposing!
gp.Save();
}
}
}
}

c# Log In click event using authentication against Active Directory through LDAP

I am quite new to c# and LDAP, I'm doing this project so that I could learn about them in a more hands on approach.
What I'm trying to create is a Log in form that has a log in click event that would authenticate the username and password after the user enters them through the active directory using LDAP.
I have read Managing Directory Security Principals in the .NET Framework 3.5 to be able to understand this subject better and I have also gone through similar topics here this one dealing with the validation in itself (c# - Validate a username and password against Active Directory?) and this one authenticating a username (c# against Active Directory over LDAP)
From the first linked topic I had learned that the following code should do the trick in authenticating a username and password:
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "LDAP://example.string.com/OU=Users, Dc=example, Dc= string, DC=com"))
{
bool isValid = pc.ValidateCredentials(User, Password);
}
So my approach to incorporate this to a click event was as follows:
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "LDAP://example.string.com/OU=Users, Dc=example, Dc= string, DC=com"))
bool isValid = pc.ValidateCredentials(User, Password);
if(isValid)
{
Main m = new Main();
this.Close();
m.Show();
}
else
{
MessageBox.Show("Invalid Username and/or Password","Error!");
textBox1.Clear();
textBox2.Clear();
textBox1.Focus();
}
Which is giving me a bool error of Embedded Statement.
I tried the other approach I had read from the second post which was to use this code which authenticates only Username:
PrincipalContext pc = new PrincipalContext(ContextType.Domain, "LDAP://example.com/OU=Computers,OU=Users,dc=example,dc=com");
UserPrincipal user = UserPrincipal.FindByIdentity(pc, "username");
bool userExists = (user != null);
But I found that I wont be able to authenticate a password using this method as UserPrincipal.FindByPassword does not exist.
I have also tried it this way but again .Password does not exist:
PrincipalContext pc = new PrincipalContext(ContextType.Domain,"LDAP://....");
UserPrincipal qbeUser = new UserPrincipal(pc);
qbeUser.EmployeeId = User;
//.Password does not exist
UserPrincipal qbePassword = new UserPrincipal(pc);
qbePassword.Password = Password;
// create your principal searcher passing in the QBE principal
PrincipalSearcher srchUser = new PrincipalSearcher(qbeUser);
PrincipalSearcher srchPass = new PrincipalSearcher(qbePassword);
// try to find that user and password
UserPrincipal founduser = srchUser.FindOne() as UserPrincipal;
UserPrincipal foundpass = srchPass.FindOne() as UserPrincipal;
if (founduser != null)
{
if (foundpass != null)
{
Main m = new Main();
this.Close();
m.Show();
}
else
{
MessageBox.Show("Password Not Valid.");
textBox2.Clear();
textBox2.Focus();
}
}
else
{
MessageBox.Show("Username Not Valid.");
textBox1.Clear();
textBox1.Focus();
}
Can someone kindly please instruct me as how one should correctly approach this.
Thank you in advance.
I have done this but not with PrincipalContext. Instead I have found many people struggling using that object.
My implemenatation was a winforms form and the submit button calls a method executing the 4 las lines of the code below.
I tested against this magnificent free to test LDAP server
var path = "LDAP://ldap.forumsys.com:389/dc=example,dc=com";
var user = $#"uid={username},dc=example,dc=com";
var pass = "password";
var directoryEntry = new DirectoryEntry(path, user, pass, AuthenticationTypes.None);
var searcher = new DirectorySearcher(directoryEntry);
searcher.PropertiesToLoad.Add("*");
var searchResult = searcher.FindOne();
I donĀ“t understand exactly what all of this lines does.
Important tips
On the path the "LDAP://" string should be on block mayus.
In the user, according to the test server you use "cn=username-admin" for validating admins, be sure to also set Authentication type to ServerBind.

UserPrincipal from Active Directory

I have problem with getting UserPrincipal from Active Directory. First of all I have used on my local environment (using not IIS but ASP.NET development Server):
User usr = new User();
usr.SoeId = Request.ServerVariables["LOGON_USER"];
usr.IP = Request.ServerVariables["REMOTE_ADDR"];
usr.FirstName = UserPrincipal.Current.GivenName;
usr.LastName = UserPrincipal.Current.Surname;
And it works fine. I got what I want. But when I install application on testing environment I got error "Object reference not set to an instance of an object". I have tried solution from here.
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain))
{
UserPrincipal up = UserPrincipal.FindByIdentity(pc, usr.SoeId);
return up.DisplayName;
// or return up.GivenName + " " + up.Surname;
}
But it does not work.
I use windows authentication. Impersonation is set to true. Please help me.
change the identity of your ApplicationPool to run using domain user.
in iis 6 right-click your application pool, go to Identity tab and set a domain user under which the pool will run.
in iis 7 right-click your application pool, select advance settings, under process model you'll find Identity, change it to use domain user.
you can also pass a domain user and pass to PrincipalContest Constructor
using (PrincipalContext context = new PrincipalContext(
ContextType.Domain,
"name of your domain",
"container of your domain",
"user#domain", //create a user in domain for context creation purpose.. this username will be constant.. you can keep it in app config
"password")){
UserPrincipal up = UserPrincipal.FindByIdentity(pc, usr.SoeId);
return up.DisplayName;
}
if your domain name is dom.com then your container would be something like DC=dom,DC=com and the user name should be given as user#dom.com or dom\user
Use this:
// find currently logged in user
UserPrincipal adUser = null;
using (HostingEnvironment.Impersonate())
{
var userContext = System.Web.HttpContext.Current.User.Identity;
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, ConfigurationManager.AppSettings["AllowedDomain"], null,
ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);
adUser = UserPrincipal.FindByIdentity(ctx, userContext.Name);
}
You must wrap any 'context' calls in HostingEnvironment.Impersonate

Categories

Resources