I have sections of my asp.net 4 MVC application that access Active Directory to check for Group Membership. When I a run the site from my computer, it works fine since I am a domain admin. When I run the site from a test computer under a standard user, I get a DirectoryServicesCOM error when trying to access AD. Obviously it's a permissions issue.
My question is, where and what within IIS do I tell to access AD as a specific account?
What are you using to access AD? I'm assuming System.DirectoryServices
What account is you app pool running as & what version of IIS? Assuming IIS7 or greater, you're probably using AppPoolIdentity which means you're accessing AD as anonymous user. Change the identity to NetworkService & it should use the machine account of your web server.
If you need privileges to do activities, then you'll need to use a specific account. If you're using AccountManagement Objects, then specify the credentials in a context class. If you're using classes in Protocols, then you do it using the connection. MSDN & Google have plenty of examples.
You should understand the security implications of the approach you use, as with all things security related.
Related
I have viewed and tried dozens of "answers" on StackOverflow, but none work.
I have a pretty simple aspx page with C# code behind.
The web site is on a Windows 2008R2 server.
The web site looks like (actual names changed):
MyServer - set for Anonymous Authentication
Application Pools
ASP.NET v4.0 Classic - .Net 4.0, Classic pipeline, App Pool Identity
MySiteAppPool - .Net 2.0, Integrated, runs under a Domain-wide Service identity (call it "mycompany\domservice")
Sites
MyMainSite - Windows Authentication, uses "MySiteAppPool"
"AutoPrint" - my web app, Windows Authentication, uses "ASP.Net v4.0 Classic" app pool, ASP.NET Impersonation enabled
My "AutoPrint" web app has a start page "AutoPrint.aspx" and code behind ("AutoPrint.aspx.cs", plus several classes).
The server and main site are not alterable, as there are several other applications under this site.
The user currently invokes this app with :
http://MyServer/AutoPrint
Everything I have tried is returning the "mycompany\domservice" result:
Request.LogonUserIdentity.Name.ToString() - returns "mycompany\domservice"
System.Environment.UserName.ToString() - returns "domservice"
System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString() - returns "mycompany\domservice"
What am I missing here? Why is this so hard?
Further clarifications:
"mycompany\domservice" - the "domservice" account is just an ActiveDirectory account in the "mycompany" domain that has permissions to read/write directories needed by the site and other applications. When installing the Site and additional web apps, we use that account as the "connect as" user.
What I am trying to do is to get the ActiveDirectory name of the Windows user account of the person who opened their browser and accessed this app. If user "JJONES" logs into Windows and launches the app with "http://myserver/autoprint", I want to get either "JJONES" or "mycompany\JJONES" as the user name.
If you use anonymous authentication, then the browser does not send any credentials (user id/password) to the server. Therefore if you want the client user id on the server, you have to use non-anonymous authentication, e.g,. Windows or Forms. You can use non-anonymous authentication and then allow or deny access to your web site to specific users or groups of users, or all users.
Thank you for all the helpful comments/suggestions.
The problem turned out to be a combination of factors. The App Pool I was using was using App Pool Identity (which has limited rights), so I had to use a specific account (the domain service account) in the "Connect as..." for the physical path credentials in order to access certain files.
Changing to use an App Pool that used an account with sufficient privileges (the domain service account) allowed me to leave the "Connect as..." using Pass-through authentication when converting to application.
Voila - I now get the user credentials using pretty much any of the proposed methods. After way too many hours of beating my head against the keyboard...
Have you looked at using HttpContext.User property ? This will give the current logged on user. After which point you may need to perform some nifty LDAP queries to get the username from AD.
See https://msdn.microsoft.com/en-us/library/system.web.httpcontext.user(v=vs.110).aspx
You may want to see the below link on how to search AD on the link "How can I search Active Directory by username using C#?"
Hope this helps you.
Seems like my local machine does not have the required permissions to write data into the Active Directory. I can read data but can not change and update it. Upon calling the .save() command I receive the next message: "Access is denied".
I do not use any login details in order to log into the Active Directory and I wish not to use any as well. I know it has something to do with the application pools and IIS generally, but I can't seem to find a working solution other than trying and changing some minor options and features.
EDIT:
This is the code I'm trying to execute:
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "DOMAINANME"))
{
GroupPrincipal group = new GroupPrincipal.FindByIdentity(pc, "GROUPNAME");
group.Members.Remove(pc, IdentityType.SamAccountName, "USERNAME");
group.Save();
}
Your intuition is correct - you need proper permissions on the application pool account.
A simplest way would be:
Create a new domain user account
Add it to "Domain admins" group
In your iis server, locate the pool your application uses and change the pool identity to the newly created user
This way all requests from users to iis are run in the context of the domain admin and thus all requests from iis to AD will succeed - domain admins can operate the AD.
Although the above solution would work, it is probably not recommended. This is because the application does many things other than just connecting to the AD and if there are places that can be misused, you risk running unwanted requests in the domain admin context.
Usually then, such application would have two layers, a front layer and a back layer. The front layer runs in a restricted context and is responsible for all user requests. This is your application. A back layer is another web application that is not accessible from internet, only from the local intranet. This application runs in the domain admin context and serves as the gateway to the AD. The front application uses the back application to talk to the AD.
In order to execute code that needs specific permissions to your Active Directory, follow these steps:
Require the user to log into the ASP.NET application.
Have your code impersonate the currently-logged in user when executing the the Active Directory portion that needs that access.
There may be slight variations depending on the version of ASP.NET you are using, but basically...
Step 1
For the user login, just use the standard ASP.NET authentication configuration. Because it's the easiest to configure (and just works with AD) I'll document Windows Authentication here. This will prompt the user with a standard Windows login dialog box - where they will need to enter their domain credentials. To configure the application, make the following changes to the Web.config
<configuration>
...
<system.web>
...
<authentication mode="Windows" />
...
</system.web>
...
</configuration>
By default, ASP.NET should already know how to talk to the Active Directory when configured for Windows Authentication, so nothing else should be required, but if you find you need a separate Role Provider, feel free to take the one we use. (We also have instructions.) But again, you shouldn't need it.
Edit: You also need to make sure IIS is configured - using inetmgr.exe - to not allow anonymous access for the application. Otherwise, it will never prompt the user to log in. We typically disable Anonymous access and enable Windows and Basic authentication - because we need to support browsers that don't support NTLM.
Step 2
Now that you have an authenticated user, you can programmatically impersonate them. The following is adapted from Impersonating the authenticating user in code:
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
try
{
// Do your writing to the AD here
}
finally
{
impersonationContext.Undo();
}
I also just discovered (while searching for reference links for this answer) that this is all pretty well documented in the MSDN article How To: Use Windows Authentication in ASP.NET 2.0
Let us know how it goes :-)
I have a few newbie web service/Windows rights questions since I've typically been a LINUX/embedded dev in the past.
What directories does a web service executing on a server have access to by default?
I ask because I tried to write to C:\ and got an access violation. I kind of assumed I would in this case, but I assume there are some areas of the file system the web service can write to and read from by default, right? Or is it just the current working directory?
*How can I give a web service permissions to look at a new directory it didn't have default access to?*
This is C# - ASMX - .NET 3.5 - IIS
The WebService doesn't really have any associated access controls associated with it (in a sense). It is however tied to the access control of the user account which is being used to run the application. By default this is usually some built in user account with limited permissions.
IIS uses a number of built-in Windows accounts, as well as accounts
that are specific to IIS. For security reasons, you should be aware of
the different accounts and their default user privileges. It can be a
security risk to change the identity of a worker process so that it
runs as an account with a high level of access, such as the
LocalSystem user account.
See a list of possible user accounts here: http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/3648346f-e4f5-474b-86c7-5a86e85fa1ff.mspx?mfr=true
If you have Anonymous Authentication enabled you can usually check the settings on that to see which account is being used to run the web service. (Depending on which version of IIS you are using, clicking Edit should let you view the default user account)
After finding the account, usually you will have to explicitly grant it the permissions on the folders (read and write) that you want to give it access to. The default user account usually has pretty limited access (and for good reason). You can grant permissions on the Security tab of the properties of any of the folders on a Windows file system (Properties->Security)
If you're using Windows Authentication, then you should have the same access rights as the authenticated user using the application as long as the resources are local to the IIS server.
I've created a custom SharePoint application which extends some of the OOTB functionality of SharePoint. Now I want to license the application and provide trial periods etc. So I want to store the licensing information in the file system/registry and check the validity of the license across the application. But even after I elevate to the application pool identity (who is just a domain user and not a system administrator as advised here http://technet.microsoft.com/en-us/library/cc678863%28office.12%29.aspx) I'm getting access denied for accessing my file.
What is the common practice to read/write/create files in the file system from SharePoint application?
Have you checked thet security logs to see which user is being denied access. I am pretty sure it will be the user who is logged into sharepoint rather than the app pool identity that is trying to access the file. The app poolidentity is usually only used in this way if the web site is using anonymous authentication.
Are you using SharePoint 2010 or 2007? What kind of Authentication? NTLM, Forms or Claims based?
If application is running under NTLM, then as Ben suggested, application will run under NTLM account and you should be able to access the resource.
If running under forms the application will run as anonymous user (local account), which will fail to access the shared resource.
I would suggest using ProcMon, it will capture the underlying access denied error and what user is being used to access that.
I guess there is no other solution apart from storing it in a custom database or a custom folder which is configured with full access for the application pool account.
I have ASP.NET page to manage objects in ActiveDirectory. I use this class
I can create a user object in AD successfully in my dev machine. When I deployed it to the server, I can only edit existing objects but I canNOT
create a new user. I always get this exception General access denied error.
Is there any setting that I missed? Please help. Thank you
Are you using static credentials within IIS? Then ensure that the account has the required permissions to create new objects.
Are you using impersonation with IIS? Then make sure you're using the correct authentication setup. You can not use the default Windows authentication if you're trying to authenticate against another machine (your domain servers). That's called the Double-Hop Problem, and has been mentioned before, usually related to SQL Server and trusted connections, but will also affect any attempt to use the impersonated users credentials against other machines.