Server permissions in web applications: it's all about context

who are you right now?

2100904507 09447c7c7a z
Credit: Tony Hall

Regardless of the platform a web application is running on, configuring permissions on the server side is tough. If your application needs to interact with the file system on the server, or the network that the server is connected to, it's common to run into identity trouble. This is usually in the form of permission denied errors or incorrect user identification over the network - and it's generally a context problem.

The basis of the difficulty is the fact that the server won't normally execute a command acting as the client on the other end of the wire. Instead, it will use a service account (either local or domain) to take action on behalf of that user. For example, PHP/Apache running on a Linux server might execute commands like a file upload as a user named 'apache' or 'www-data'. Because of this, the apache user or its group needs to have write permissions to your upload folder on the server. Likewise under IIS/Windows, your application pool is assigned a user context to run under.

Sometimes however, you need to 'act' as the current user of the application, not the service account. Take for example Active Directory operations within an application using Windows Authentication. When the user arrives at your application, you want to fetch the domain\user of the visitor for use in the software. Depending on where you access a 'User' in your application, it could either mean the web user making the request or the service account processing the request. In a 3-tier system,  the data tier won't have direct access to the HttpContext unless you pass it all the way down and thus won't know about the web user. It will however know about the system user that it's executing under, aka the service account. 

It's a simple distinction but it is an easy one to mix up or overlook. It's also tricky to debug and troubleshoot. In a recent blunder, I needed to auto discover an Active Directory server on the network and use it to fetch the profile information of the requesting user. While initializing a PrincipalContext instance, I passed what I thought was the requesting user's domain into the constructor using:

System.Environment.UserDomainName

Sure sounds like the right thing. The Principal Context then finds a Domain Controller to query under that provided domain. The obvious mistake here is that I was actually passing in the domain of the executing service account, not the web user. If the web user was under the same domain as the service account, this worked fine, which was the most common case. In the edge cases where they were not, the user profile was always null because they belonged to a different domain. Tough to weed out when it mostly works. 

This type of issue is also very common when your software has to do anything with the file system. Routine tasks like writing to a text or log file, uploading an image or pdf, moving or deleting documents, become an exercise in frustration as you battle permission denied errors. Rather than giving up and simply making everything wide open permissions for everyone (which is more common than you'd imagine), it's important to stop and think about exactly what the context is at the point where the command is executed. If you are careful and consider 'who am I right now'? when programming this type of operation, you'll save yourself a world of pain.

Related:
ITWorld DealPost: The best in tech deals and discounts.
Shop Tech Products at Amazon