User Principal is always null - c#

I am logged in under user User001 under domain DomainA and with password Pass001.
I use this code
//var principalContext = new PrincipalContext(
//ContextType.Domain,
//"DomainA",
//"User001",
//"Pass001");
var principalContext = new PrincipalContext(
ContextType.Domain,
domain,
userName,
password);
var userPrincipal = new UserPrincipal(principalContext);
And userPrincipal is always NULL.
How to fix it?

Somehow this code I found is working fine...
using (var context = new PrincipalContext(ContextType.Domain))
{
using (UserPrincipal principal = UserPrincipal.FindByIdentity(context, userName))
{
var uGroups = principal.GetGroups();
foreach (var group in uGroups)
{
Debug.WriteLine(group.DisplayName);
}
}
}

Related

Connect to another domain Active Directory in ASP.NET

I am trying to connect to another domain using from my C# code but I get an error.
Here is my code:
doLog("Going For establishing Connection");
var username = "cn=Directory Manager";
var password = "somepassword";
using (var context = new PrincipalContext(ContextType.Domain, "LDAP://10.10.10.132:2232", username, password))
{
using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
{
doLog("In the principal searcher");
foreach (var result in searcher.FindAll())
{
DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
doLog("Looping result:" + de.Properties["givenName"].Value);
Console.WriteLine("First Name: " + de.Properties["givenName"].Value);
}
}
}
It is working in java but from .net it always throw an error on this line
using (var context = new PrincipalContext(ContextType.Domain, "LDAP://10.10.10.132:2232", username, password))
This is the error I get:

How to get group managed service accounts using UserPrincipal.FindByIdentity?

I have one gMSA user created. I am trying to get the user sid-
ContextType contextType= ContextType.Domain;
PrincipalContext domainContext = new PrincipalContext(contextType, domain);
using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName))
{
if (foundUser != null)
{
identity = foundUser.Sid.Value;
result = true;
}
}
The gMSA user is under a domain such as contoso.ab.cd.com
I ran in to this issue as well. In my environment, I noticed that the gMSA accounts are not in the UserPrincipal at all. Rather, they are in ComputerPrincipal. Try the following:
ContextType contextType= ContextType.Domain;
PrincipalContext domainContext = new PrincipalContext(contextType, domain);
using (var foundUser = ComputerPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName))
{
if (foundUser != null)
{
identity = foundUser.Sid.Value;
result = true;
}
}

Find username from Active Directory using email id

I am finding user name from Active Directory by passing email id. It is working fine. But it takes 30-40 seconds to get the username. Is there any other better way to find the username from Active Directory by email address?
Please refer to my code:
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, "domainname"))
{
UserPrincipal userPrincipal = new UserPrincipal(context);
PrincipalSearcher principalSearch = new PrincipalSearcher(userPrincipal);
foreach (UserPrincipal result in principalSearch.FindAll())
{
if (result != null && result.EmailAddress != null && result.EmailAddress.Equals(user.Email, StringComparison.OrdinalIgnoreCase))
{
user.FirstName = result.GivenName;
user.LastName = result.Surname;
}
}
}
You don't need to enumerate all users to to find one of them! Try this code:
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, "domainname"))
{
UserPrincipal yourUser = UserPrincipal.FindByIdentity(context, EmailAddress);
if (yourUser != null)
{
user.FirstName = yourUser.GivenName;
user.LastName = yourUser.Surname;
}
}
If that shouldn't work, or if you need to search for several criteria at once, used the PrincipalSearcher with the QBE (query-by-example) approach - search the one user you need - don't cycle through all users!
// create your domain context
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, "domainname"))
{
// define a "query-by-example" principal -
UserPrincipal qbeUser = new UserPrincipal(ctx);
qbeUser.EmailAddress = yourEmailAddress;
// create your principal searcher passing in the QBE principal
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
// find all matches
foreach(var found in srch.FindAll())
{
// do whatever here - "found" is of type "Principal" - it could be user, group, computer.....
}
}
using System.DirectoryServices.AccountManagement;
// Lock user
using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
{
UserPrincipal yourUser = UserPrincipal.FindByIdentity(context, logonName);
if (yourUser != null)
{
if(!yourUser.IsAccountLockedOut())
{
yourUser.Enabled = False;
yourUser.Save();
}
}
}

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

Setting DistinguishedName using UserPrincipal

When using DirectoryEntry, it is possible to set the CN of the new user account, but how to do it using UserPrincipal? The property is readonly.
// From : http://msdn.microsoft.com/en-us/magazine/cc135979.aspx
DirectoryEntry container = new DirectoryEntry("LDAP://ou=TechWriters,dc=fabrikam,dc=com");
// create a user directory entry in the container
DirectoryEntry newUser = container.Children.Add("cn=user1Acct", "user");
// add the samAccountName mandatory attribute
newUser.Properties["sAMAccountName"].Value = "User1Acct";
// save to the directory
newUser.CommitChanges();
But using UserPrincipal:
// For the example
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, null, "ou=TechWriters,dc=fabrikam,dc=com")
{
using (UserPrincipal user = new UserPrincipal(ctx, "User1Acct", "pwd", true))
{
// I would like to do :
user.DistinguishedName = "user1Acct";
//
user.Save();
}
}
Not the answer you want, but to my knowledge its not doable that way... The CN is 'protected' om the userprinciple class, as too much elsewhere relies on that being stable information.
I don't know why one would mix things up, but you could try this:
using (var ctx = new PrincipalContext(ContextType.Domain, null, "ou=TechWriters,dc=fabrikam,dc=com"))
{
using (var user = new UserPrincipal(ctx, "User1Acct", "pwd", true))
{
user.Save();
}
using (var entry = new DirectoryEntry("LDAP://cn=User1Acct;ou=TechWriters,dc=fabrikam,dc=com",null,null,AuthenticationTypes.Secure))
{
entry.Rename("cn=user1Acct");
}
}
(Maybe getting the LDAP string from the userPrinciple instead of hardcoding)
I do not have the possibillity to test this though..

Categories

Resources