UserPrincipal from Active Directory - c#

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

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

Get current active directory user and group c#

I'm trying to use the following code to get the local logged in user for my web application based on AD.
Here is what i'm trying;
string CurrentUser = WindowsIdentity.GetCurrent().Name;
PrincipalContext context = new PrincipalContext(ContextType.Domain, "isd");
UserPrincipal upUser = UserPrincipal.FindByIdentity(context, CurrentUser);
if(upUser != null)
{
}
However, it returns "IIS APPPOOL\DefaultAppPool" as the user and not isd\whoever
It's IIS7 and .net 4
Thanks

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();
}
}
}
}

Get domain chosen by PrincipalContext

I'm creating a custom login functionality for asp.net which validates against active directory. The user must be able to login with only his username or with his username and a domain (and a password in both cases).
Code:
AuthUser user = Authentication.getDomainAndUserName(givenUsername);
bool validAccount = false;
PrincipalContext network = null;
if (user.domain != "") network = new PrincipalContext(ContextType.Domain, user.domain);
else network = new PrincipalContext(ContextType.Domain);
if (UserPrincipal.FindByIdentity(network, IdentityType.SamAccountName, user.username) != null) {
validAccount = network.ValidateCredentials(givenUsername, givenPassword, ContextOptions.Negotiate);
}
The "AuthUser" contains the username and, if given, the domain. Now if a user didn't explicitly specify the domain the above still works fine.
So if you call
new PrincipalContext(ContextType.Domain);
It seems that the domain is set automatically.
In that case, how can i find out the domain it used?
You always can get the domain used from the user principal returned from UserPrincipal.FindByIdentity()

Cannot add an IIS Application Pool to a local user group via C#

I am trying to add an IIS Application Pool user to a local user group remotely via C# and am having some difficulty.
I have tried the two approaches below:
// This results in a ArgumentNullException because user is never set
using (PrincipalContext pc = new PrincipalContext(ContextType.Machine, serverName))
{
UserPrincipal user = UserPrincipal.FindByIdentity(pc, String.Format(#"IIS APPPOOL\{0}", rootApplicationPoolName));
GroupPrincipal myGroup = GroupPrincipal.FindByIdentity(pc, "mygroupname");
myGroup.Members.Add(user);
myGroup.Save();
}
Also:
// This results in a NoMatchingPrincipalException saying the user could not be found
using (PrincipalContext pc = new PrincipalContext(ContextType.Machine, serverName))
{
GroupPrincipal myGroup= GroupPrincipal.FindByIdentity(pc, "mygroupname");
myGroup.Members.Add(pc, IdentityType.Name, String.Format(#"IIS APPPOOL\{0}", appPoolName));
myGroup.Save();
}
I can manually add this user to the group and it works just fine.
What am I missing?

Categories

Resources