System.DirectoryServices.AccountManagement.UserPrincipal - localhost but not iis
Asked Answered
C

3

9

Why does the code below work fine when I run my web application localhost but not when I install it to an IIS server?

using (HostingEnvironment.Impersonate())
{
    UserPrincipal activeUser = UserPrincipal.Current;
    String activeUserSid = activeUser.Sid.ToString();
    String activeUserUPN = activeUser.UserPrincipalName;
}

Please don't suggest I stick with HttpContext.Current.User as it doesn't provide access to SID or UPN without additional calls to Active Directory.

The web application will be used by Windows authenticated users from three separate domains, the web server is hosted in a fourth domain. The Application Pool is configured to run under the NetworkService identity and the web app configuration has identity impersonation set to true.

The error message when it runs on IIS is:

Error in Page_Load(): UserPrincipal.Current.
System.InvalidCastException: Unable to cast object of type 'System.DirectoryServices.AccountManagement.GroupPrincipal' to type 'System.DirectoryServices.AccountManagement.UserPrincipal'.
at System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext context, IdentityType identityType, String identityValue)
at System.DirectoryServices.AccountManagement.UserPrincipal.get_Current()
at webapp.Details.Default.Page_Load(Object sender, EventArgs e)

EDIT: Tried both the following and unfortunately get the same error.

UserPrincipal userPrincipal = UserPrincipal.Current;
Response.Write(userPrincipal.Name);
Principal userOrGroup = UserPrincipal.Current;
Response.Write(userOrGroup.Name);
Cancroid answered 21/6, 2012 at 12:40 Comment(0)
L
2

It seems like need some other method to determine user.
Here description from msdn for property:
"Gets a user principal object that represents the current user under which the thread is running."
So, UserPrincipal.Current returns user under what IIS running.

http://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.userprincipal.aspx

Loriannlorianna answered 21/6, 2012 at 14:35 Comment(2)
I think you're right. This doesn't work either... var wi = HttpContext.Current.User.Identity as WindowsIdentity; using (wi.Impersonate()) { UserPrincipal up = UserPrincipal.Current; activeUserUPN = up.UserPrincipalName; activeUserSid = up.Sid.ToString(); }Cancroid
"the current user under which the thread is running" in IIS is most likely the IIS App Pool Identity; but when running on your PC in Visual Studio, Casini or IIS Express, it is running as you. In that case your identity is shared by the client requesting the page and the locally running development server.Finochio
W
4

I had a lot of issues deploying UserPrincipal.Current and still don't fully understand why.

I finally ended up using PrincipalSearcher, and created the following function to do what I thought UserPrincipal.Current was doing.

private UserPrincipal GetActiveDirectoryUser(string userName)
{
    using(var ctx = new PrincipalContext(ContextType.Domain))
    using(var user = new UserPrincipal(ctx) { SamAccountName = userName})
    using(var searcher = new PrincipalSearcher(user))
    {
        return searcher.FindOne() as UserPrincipal;
    }
}

And I passed System.Web.HttpContext.Current.User.Identity.Name into that method as the userName.

Weissman answered 13/1, 2014 at 19:32 Comment(2)
I get this error: System.ObjectDisposedException: Cannot access a disposed object. Object name: 'PrincipalContext'. at System.DirectoryServices.AccountManagement.PrincipalContext.CheckDisposed() at System.DirectoryServices.AccountManagement.PrincipalContext.get_ContextType() at System.DirectoryServices.AccountManagement.Principal.get_Name() at System.String.Concat(Object[] args) at Admin_Click(Object sender, EventArgs e)Beecher
I tried multiple things in my MVC Application. DirectoryEntry de = new DirectoryEntry("WinNT://" + Environment.UserDomainName + "/" + userId); string Username = de.Properties["fullName"].Value.ToString(); Then i tried System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName; Then Tried your solution, and it was the only one to work when deploying out to my production server... not sure why. All worked locally...Plautus
L
2

It seems like need some other method to determine user.
Here description from msdn for property:
"Gets a user principal object that represents the current user under which the thread is running."
So, UserPrincipal.Current returns user under what IIS running.

http://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.userprincipal.aspx

Loriannlorianna answered 21/6, 2012 at 14:35 Comment(2)
I think you're right. This doesn't work either... var wi = HttpContext.Current.User.Identity as WindowsIdentity; using (wi.Impersonate()) { UserPrincipal up = UserPrincipal.Current; activeUserUPN = up.UserPrincipalName; activeUserSid = up.Sid.ToString(); }Cancroid
"the current user under which the thread is running" in IIS is most likely the IIS App Pool Identity; but when running on your PC in Visual Studio, Casini or IIS Express, it is running as you. In that case your identity is shared by the client requesting the page and the locally running development server.Finochio
M
0

Yes, its because you are disposing of the returned UserPrincipal object due to the multiple using statements. Remove 'ctx' from the using statement, then it becomes the callers responsibility to dispose of the returned object.

Muniment answered 23/1, 2019 at 11:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.