Create WindowsIdentity using just a domain and username - c#

I am building a site that gets user information using the WindowsIdentity of the current user. The main info I get from this is the ssid.
I do this for the current users as follows
IntPtr logonToken = WindowsIdentity.GetCurrent().Token;
WindowsIdentity windowsId = new WindowsIdentity(logonToken);
string ssid = windowsId.User.ToString();
What I need to do now, and am failing at, is getting the ssid for any arbitrary username that exists on the domain.
I tried WindowsIdentity(string), but that gave me a SecurityException
The name provided is not a properly formed account name.

How are you formatting the principal? Generally they take the form of user#domain.ext, so if your AD provides principal resolution on say example.com, a user principal name (UPN) may look like: joe.bloggs#example.com. The WindowsIdentity(string) constructor accepts a UPN, not an older format username EXAMPLE\joe.bloggs

Related

How can I access Active Directory data without exposing the password

I am just learning to access my Active Directory and need to figure out if it is possible to access the information without having the user account password in the code. This code works:
DirectoryEntry SharePointUpdate = new DirectoryEntry("LDAP://" + "comm2k8-dc3", "juser01", "password", AuthenticationTypes.Secure);
When I try this code:
String strPath = "LDAP:// DC=MYOrganization"
DirectoryEntry SharePointUpdate = new DirectoryEntry(strPath);
I get this error
"A referral was returned from the server.\r\n
Am I missing something??
I do not want to have the user name and password in the code. Is there anyway I can do this?
Is this code running in the context of either a domain service account or Network Service/Local System on a domain joined machine? If so, you can use that security context to access AD.
Your LDAP://DC=MYOrganization looks potentially strange. Is your domain really a single label domain called "MyOrganization", or does it have a legal FQDN? If it's called MyOrganization.net, for example, you would connect to LDAP://DC=MyOrganization,DC=net.

A reliable way to obtain the Windows user display name

I need to get the Display Name of the current user, and cannot find a solution that always works. Just for clarity, I'm not looking for the username. I need the "John Doe". The value displayed on the Start Menu.
There are many posts about this question however none have solved my problem.
Get Windows User Display Name
How do I get the AD Display Name of the currently logged in user
These two posts lead me to:
PrincipalContext context = domain.Equals(Environment.MachineName, StringComparison.CurrentCultureIgnoreCase) ?
new PrincipalContext(ContextType.Machine) :
new PrincipalContext(ContextType.Domain, domain);
UserPrincipal userPrincipal = new UserPrincipal(context) { SamAccountName = username };
PrincipalSearcher searcher = new PrincipalSearcher(userPrincipal);
userPrincipal = searcher.FindOne() as UserPrincipal;
string displayName = userPrincipal.DisplayName;
And this code works for the most part. However if the user's has disabled/stopped the Server service on his/her computer I get an exception saying "The Server service is not started."
System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName
Same error.
How to get logged-in user's full name in windows?
StringBuilder name = new StringBuilder(1024);
uint userNameSize = (uint)name.Capacity;
const int NameDisplay = 3;
GetUserNameEx(NameDisplay, name, ref userNameSize)
Returns no error, but an empty string if the user is not on a domain.
How do you read the user's display (first and last) name on all versions of Windows reliably?
// get SAM compatible name <server/machine>\\<username>
if (0 != GetUserNameEx(2, username, ref userNameSize))
{
IntPtr bufPtr;
try
{
string domain = Regex.Replace(username.ToString(), #"(.+)\\.+", #"$1");
DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, domain);
DomainController dc = DomainController.FindOne(context);
if (0 == NetUserGetInfo(dc.IPAddress,
Regex.Replace(username.ToString(), #".+\\(.+)", "$1"),
10, out bufPtr))
{
var userInfo = (USER_INFO_10) Marshal.PtrToStructure(bufPtr, typeof (USER_INFO_10));
return Regex.Replace(userInfo.usri10_full_name, #"(\S+), (\S+)", "$2 $1");
}
}
finally
{
NetApiBufferFree(out bufPtr);
}
}
With the above I get an ActiveDirectoryObjectNotFoundException with message "Domain controller not found in the domain.." when DomainController.FindOne is called.
I haven't found a registry setting for the display name.
I'm don't know what else to try. Please help.
All of the above methods will only work if you are on a domain. If you are not, then you must rely on the local user account store. The following details how to retrieve this info: How can I get a list Local Windows Users (Only the Users that appear in the windows Logon Screen). In a domain situation though, the users account will not be in the local store.
If you are on a domain but not connected to the domain controller, the Display Name will not be readily available to you. This information is stored on the domain controller, not the local user's computer. If your users are on a domain, they really shouldn't be able to disable the Server service(use GPOs). Also, they lose much more than the ability to retrieve their user account by disabling that service.
I would check for domain availability before trying to get the display name. If it fails, display a message indicating the failure. There are potentially too many edges cases here to make it work accounting for all of them. Go with the scenario that you intend the program to be used under, and give an error message for the others.

"Encoded" login names in SharePoint Client Object Model

I'm writing a small .NET proof-of-concept console app that performs a series of actions on a SharePoint document library. I noticed that the following methods expect an "encoded" login name - that is, login name including provider information, e.g. i:0#.w|DOMAIN\user.
context.Web.EnsureUser(encodedLoginName);
context.Web.SiteUsers.GetByLoginName(encodedLoginName);
How do I reliably convert a user name such as DOMAIN\user to this encoded format in the SharePoint Client Object Model?
I've read a couple of blog posts that address this issue with the SPClaimProviderManager, which is not available in the client API.
I am able to get the encoded login name using the ResolvePrincipal utility method:
using SP = Microsoft.SharePoint.Client;
//...
// resolve user principal using regular login name or e-mail:
var userPrincipal = SP.Utilities.Utility.ResolvePrincipal(
context,
context.Web,
"DOMAIN\\user", // normal login name
SP.Utilities.PrincipalType.User,
SP.Utilities.PrincipalSource.All,
context.Web.SiteUsers,
false);
context.ExecuteQuery();
// ensure that the user principal was resolved:
if (userPrincipal.Value == null)
throw new Exception("The specified user principal could not be resolved");
// get a User instance based on the encoded login name from userPrincipal
var user = context.Web.SiteUsers.GetByLoginName(userPrincipal.LoginName);
context.Load(user);
context.ExecuteQuery();
This seems to work as intended. However, if there is a better way or caveats that I should be aware of, please let me know.

Obtaining the SecurityIdentifier (SID) from just a domain username (c#)

I wish to obtain the domain SID from a user account that has been used to access my web page, but...
In some instances, you dont have access to the HttpContext object to call HttpContext.Current.Request.LogonUserIdentity.User.Value
All the static function is able to accept is a user-name as a string, and a domain-name as a string.
If the domain is left blank, it is amused that the user account name is within the same domain as the IIS server that the process is executing upon. :/
your help would be most appreciated as always.
Cheers.
To get the a user's domain, you can use LookupAccountName. In case you need a pinvoke sample, get it from pinvoke.net
You pass in DOMAIN\UserName to the function. The LookupAccountName function will give you back the user SID and the domain name.
I suspect that you don't really need to know the domain SID. I would think the returned domain name should be enough for you. If you really want to know the domain SID, you can extract it directly from a the returned user SID.
A user SID is always starting with a domain SID. For the details of how a SID structure looks like and how to extract the domain SID, please check here
Try using Directory Services? Need .Net 3.5 for this:
public UserPrincipal GetUserPrincipal(string userName)
{
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, LDAPDomain, LDAPUser, LDAPPassword);
return UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, userName);
}
You can then use the UserPrincipal Class which has a .Sid method.
I set my Domain and AD account info from the web.config like so
private String LDAPDomain
{
get
{
return ConfigurationManager.AppSettings["LDAPDomain"];
}
}

ASP.NET - Get the Principal / Relative Identifier (RID) for a DirectoryEntry / SID

I am using Active Directory in a custom MembershipProvider class to authenticate users in an ASP.NET 2.0 intranet application and associate their sid with a profile for the application.
When the ActiveDirectoryMembershipProvider is used, the ProviderUserKey object for the MembershipUser is as follows
SecurityIdentifier sid = (SecurityIdentifier)Membership.GetUser().ProviderUserKey;
string sidValue = sid.ToString();
/* sidValue = "S-1-5-21-XXXX-XXXX-XXXX-YY" */
As I understand it, YY is the principal within the namespace (also referred to as a group/domain).
When using the custom MembershipProvider, I can get the sid using the objectSid property of a DirectoryEntry object
DirectoryEntry entry = new DirectoryEntry(path, username, password);
SecurityIdentifier sid = new SecurityIdentifier((byte[])entry.Properties["objectSid"].Value, 0);
string sidValue = sid.ToString();
/* sidValue = "S-1-5-21-XXXX-XXXX-XXXX" */
The sidValue in this case is identical, except it does not contain the principal YY.
My question is two-fold
Is the principal required in order to uniquely identify an individual?
Is it possible to obtain the principal from the DirectoryEntry object (or through any other classes available in System.DirectoryServices)?
EDIT:
Having done some further reading ({1} {2}), I now know that the sid can change if the user is moved from one group/domain to another. In light of this, would using the GUID defined in the DirectoryEntry Properties["objectGUID"] be a better choice for uniquely identifying a user?
The objectGUID is the best choice for identifying a user account. I highlight this because the objectGUID is unique and fixed for an instance of an account. If you delete and recreate the account with the same distinguishedName you'll get a different objectGUID. So, objectGUID doesn't identify the user, it identifies the account.
So, if you want to identify the account, use objectGUID.
Sometimes, accounts can be deleted and recreated by admins to solve problems. If you need to identify the user even after this has happened, you need to pick something else on the account object. That will probably have to depend on your account definition policies. Maybe you have sAMAccountNames that are not based on the user's name? Maybe the admins populate employeeid or employeeNumber? Maybe they enforce uniqueness for displayNames?
Here's a link to AD attribute info.
Here's a link to DirectoryEntry Properties.

Categories

Resources