(This question is similar to Get UPN or email for logged in user in a .NET web application, but not quite.)
In a .NET (C#) web application using Windows authentication, I'd like to find the UPN of the signed-in user.
I know how to do this by querying Active Directory: take the 'DOMAINNAME\userName' from HttpContext.Current.User.Identity as WindowsIdentity
; look up DOMAINNAME under the ldap://RootDSE
and find its dnsRoot
; query for (&(objectCategory=person)(objectClass=user)(sAMAccountName=...userName...))
under ldap://...dnsRoot...
; get this entry's userPrincipalName
property. (More detail is in answer https://stackoverflow.com/a/513668/223837).
My question: Can the UPN be found without a call to Active Directory? Given Microsoft's focus on using UPNs everywhere, isn't the UPN already stored somewhere in the token which is created when the user authenticates to the web server?
(Supporting observation: If I run whoami /upn
on Windows 7, then Wireshark does not show any Active Directory connections.)
(If it makes any difference: note that our web application does not use impersonation, i.e., our web app does not run under the user identity.)
Try System.DirectoryServices.AccountManagement.UserPrincipal.Current
, which has the property UserPrincipalName
. Of course, that would require the application to be running under Windows authentication.
Edit Meh, it looks like this API still performs a directory lookup.
I was having issues with the Active Directory query when using System.DirectoryServices.AccountManagement.UserPrincipal.Current
, so I resorted to using GetUserNameEx
with the NameUserPrincipal
format.
This function gets the information about the current user, so it does require that you impersonate if you are not already. In C# it can be done by importing the function:
public enum EXTENDED_NAME_FORMAT
{
NameUnknown = 0,
NameFullyQualifiedDN = 1,
NameSamCompatible = 2,
NameDisplay = 3,
NameUniqueId = 6,
NameCanonical = 7,
NameUserPrincipal = 8,
NameCanonicalEx = 9,
NameServicePrincipal = 10,
NameDnsDomain = 12
}
[DllImport("secur32.dll", CharSet = CharSet.Auto)]
public static extern int GetUserNameEx(int nameFormat, StringBuilder userName, ref int userNameSize);
Then calling it like this:
string upn = null;
StringBuilder userName = new StringBuilder(1024);
int userNameSize = userName.Capacity;
if (GetUserNameEx((int)EXTENDED_NAME_FORMAT.NameUserPrincipal, userName, ref userNameSize) != 0)
{
upn = userName.ToString();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With