How to test asp.net location folder authorization programmatically - asp.net

I have an location element in my web.config like so:
<location path="Admin">
<system.web>
<authorization>
<allow roles="Domain\Development"/>
<deny users="*" />
</authorization>
</system.web>
</location>
This works to only allow members of the development group access to this folder.
I was wondering if there is a way to simply test if a user has access to this folder?
One scenario is creating menu items. I'd simply like to hide or not render links to pages in this folder if the user does not have the proper rights.
Is there a way to do this in code. I don't want to have to hard code a check for membership in Domain\Development rather I'd like to use asp.net to tell me if this current user has access.
This would be nice if the rules get more complicated etc. Also having this in one place enforces DRY (Don't Repeat Yourself).

Through a related question I found the answer. Call UrlAuthorizationModule.CheckUrlAccessForPrincipal. (Documentation is here.) You can give it a path and a user (such as Page.User for the current user), and it will tell you if the user can access that path.
I like this for exactly the reason you mentioned: You can put your access logic in one place.

Related

Hide folder in asp.net with deny roles

I have this configuration below to hide a folder from users in a specific group. It works on one domain but when I trying to deploy it to another one it doesn't.
I know that the settings is in the right place in the web.config and right formatted because if I change to deny users="*" no one will see it the folder (almost like I want but I want only hide for a specific AD group) and I know for a fact that I have the right AD group for it too since I'm using it in my code (doing a IsInRole check).
<location path="Folder">
<system.web>
<authorization>
<deny roles="domain\group"/>
</authorization>
</system.web>
</location>
Using Windows Athentications
What can I have missed on the second IIS/Domain? (Don't forget that it works on the "first" Domain/IIS)
I was trying to make the first iis that worked to have the same settings as the one that didn't but obviously I failed. When I found the problem it was that Anonymous - was enabled and Windows Authentications was disabled, I switch those and It now works. (I'm sure I trided to set the "working" iis in the same Authentication state but since that was of an older version I may have failed)

IIS 7.5 and making anonymous authentication/forms authentication play nicely together

I've got an ASP.NET MVC 4 application that I run under the site level of an IIS web site.
So the dir structure looks like this:
\IIS
\Site
\bin
\Content
\Views
The MVC 4 app uses Forms Authentication via Username and Password, but I have a requirement to lock down the full site and turn off anonymous authentication at the IIS level.
The goal of this requirement is to allow users only to land on a home page and logon page. The problem is if I turn off anonymous authentication then users can't even get to home or login.
Another thing we want to prevent a user from being able to go to /Content/Scripts/MyScript.js in their browser.
I'm using bundling so those file are there and don't get used by me besides when I bundle things up.
Is this even possible since IIS and MVC 4 auth are at completely different level? If it is possible what options do I have?
Chris Pratts answer is correct. You can successfully turn of anonymous authentication and let MVC4 handle all of that for you.
Make sure in your web.config you have the following
<modules runAllManagedModulesForAllRequests="true"></modules>
In your system.webserver section.
Another thing you can do is make use of the locations tags in IIS to prevent user access to different parts of the site.
For example, you could put this in your web.config
<location>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
This ensures that only authenticated users can access the site. You can then further refine this.
<location path="External">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
Basically, now any request to /External will be allowed for all users (regardless of authentication). You will probably want to put all your scripts in here that you need unauthenticated users to access.
If there was a specific directory you didn't want anyone to access, you could do something like
<location path="/Content/Scripts">
<system.web>
<authorization>
<deny users="*" />
</authorization>
</system.web>
</location>
Now any access to that location will be prevented by default in IIS. Give that a try, it should satisfy your requirement to have the scripts available for bundling, but not accessible if someone browses directly to it.
I only halfway got what I wanted, but here is what I ended up doing. I have anonymous authentication enabled at the site level and used Forms authentication for specific controllers. This was how I originally had it so nothing changed here.
Since I am using bundles the users never really need to look at the .js so I used Request Filtering by file extension so block any .js and even .css I don't want exposed.
This works because the bundling doesn't make http requests to those files and the bundles themselves don't have the normal JavaScript and CSS file extensions.
You don't handle this at the IIS-level. You simply allow Anonymous Auth and then add [Authorize] to every controller. Then only on your home and login actions add the attribute [AllowAnonymous].
As to the second part of your question, you can't really stop this. MVC bundles on the fly, so it needs the actual files to be there. If they're never referenced, though, they're black holes: the user would have no way of knowing what file to request, so it's kind of security by obscurity.

Unauthenticated users can't see images in website

When I run my website through debug mode in visual studio everything looks great and all the images on the page show up fine. But once I deploy my website to an IIS7 web server (doubt that other versions would make any difference, but you never know) then users can't see the images on the site until they log in.
The website is an asp.net MVC site and I'm new to MVC, though I do have lots of experience with asp.net forms. It seems that only authenticated users are allowed to access the images folder, and there is an authorization section in my web.config saying that only admins can access the site, so how do I make it so that all users, authenticated or otherwise can view the images?
-- Update --
I tried putting in the configuration block suggested, which from everything I can tell makes perfect sense, but it didn't seem to make a difference. The sample below has Content/Images for the path but before that I tried just Content, since it's OK for everything in there to be accessible. I also tried setting the allowOverride setting to false, which also didn't seem to make a difference.
<location path="Content/Images">
<system.web>
<authorization>
<allow users ="*" />
</authorization>
</system.web>
</location>
--Update 2--
Funny thing is that I don't even see any explicit deny entries in my web.config, just an allow for admin's, and when I went into IIS 7 and used the UI to allow all users access to the Content directory it didn't show any deny's on the list either. But then again, this project works fine when I just debug it from my personal computer, it's only after I deploy it that I have problems...
<authorization>
<allow roles="admin" />
</authorization>
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>
In your web.config file, after the </system.web> tag, add the following
<location path="images">
<system.web>
<authorization>
<allow users ="*" />
</authorization>
</system.web>
</location>
where path="images" is the name of the folder with your images/css.
Update:
If you're using ASP.NET MVC, I would remove the authorization declaration in the web.config file and use the [Authorize] attribute on the controllers that need to be locked down.
You can also specify the roles you want to grant access to using [Authorize("admin")].
By default, the configuration you define in a Web.config file, applies to every subdirectory of its containing folder. If you have a Web.config in the application root, that configuration will propagate to every subdirectory, including those where you have images and Css style sheets. So, if you have in your root Web.config a rule like this one:
<system.web>
...
<authorization>
<deny users="?"/>
</authorization>
...
</system.web>
anonymous users will not be able to access the resources needed to display the page like you would expect it.
To fix it, you need to include another Web.config in every subdirectory that has presentation resources, and apply the rules you want to override. In your case, this should do the work:
<?xml version="1.0"?>
<configuration>
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</configuration>
If you are using Themes, place a single Web.config file in the theme folder.
Just ran into the same problem. We noticed it on our Login page. The CSS and images weren't loading (they were under the content directory). Adding IUSR to the folder with Read privileges fixed it for us.
Old question but I came across the same problem and found the answer.
I had created a new folder for the Membership pages that I wanted logged-in users to have access to, but the images wouldn't show up in them!
It turns out that no matter what I tried I couldn't set a relative path to the images from within the Members folder.
The problem was the html image (as far as I could tell anyway, correct me if I'm wrong).
I swapped it out for an asp:image with a relative path and now it works great.
My new code: asp:image runat="server" id="Logo" ImageUrl="~/Images/logo.jpg"
Notice the ' ~/ ', that wouldn't work for me with
I tried: img src="../Images/logo.jpg", img src="~/Images/logo.jpg", img src="/Images/logo.jpg", etc. to no avail.
Hope this answer helps someone solve this problem more quickly in the future.
Try browsing the image file directly and see if that comes up for an anonymous user. In IIS 7, there is a way in which you can authorize anonymous users directly from your UI [which in turn would create the web.config if it doesn't exist].
Folder -> .NET Authorization Rules -> Add Allow Rule
Are you using membership framework. I suspect that you have misconfigured your permission settings in web.config and your images folder is only allowing authorised requests. This can be easily change via web.config. Just remove the folder name from your authorised section and this should solve the problem.
For your reference this should be the section in web.config if you are using membership framework :
<authorization>
<deny roles="xyz" />
</authorization>
We came across the same problem in our project and found a solution, although we are not sure about the reasons of this behaviours.
We had a similar scenario, with a folder containing all our png images. Our marketing colleague wanted to rename some of them, so to make it easier for her, we shared (this might be the key) that folder, granting read/writer rights to her.
From this point, the images started behaving as you describe, requiring authorization for being accessed. No unauthorized user could see them any more.
We realized that the problem was related to sharing the folder because it started happening at that point of time. Otherwise we still don't see any relationship among ASP.NET MVP user authorization/login and hard disk user rights. We could have expected an IO Exception or something similar, but not this behaviour.
After checking the folder, and comparing with other folders, we realized that after sharing, the permissions on the folder had slightly changed. Mainly they did not inherit from its parent folder anymore and some permissions such as CREATOR OWNER and MACHINE_NAME\Users had dissapeared (although IUSR and the app pool user were still there).
So, we renamed that folder, created a new one with the same name, and copied the content from the old folder to the new one. The new folder had the permissions inherited from its parent and everything started to work perfectly again.
It solved our problem, but we are still not sure why this all happened this way.
Regards

ASP.NET Active Directory Nested Authorization Issue

I'm working on an internal ASP.NET application that uses an Active Directory distribution list for managing who has access to the web site.
However, due to the fact that this distribution list could contain both users and groups, I had to develop a solution for checking to see if the current user is able to access this site (e.g. They could be in a group that is a part of this distribution list). The default Windows authentication mode does not support this type of hierarchical structure.
My question is how can I ensure that every resource in this web site can only be accessed by those who are in this distribution list? I am currently using a custom attribute applied to every page that checks the user's credentials and redirects to a 'No Access' page if they are not a member of the DL. However, I'm thinking that there must be a better way to do this that doesn't require me to use the attribute on every page which is created for this site?
Any help is appreciated!
The simplest fix to avoid duplication without changing the underlying authentication scheme - Instead of using it on every page, you could do hook into the Session_Start event and store the authentication value there, and check this value on an appropriate event of your master page if you have one. (again this is least effort and an answer directed at your direct question)
Update (Response to Comment)
To manage permissions for a group use the following xml block. Note that this will do what you mentioned in your comment on the other answer: this will block image files, etc... too.
<authorization>
<allow roles="domain\group"/>
<deny users="*"/>
</authorization>
Original
The best way is to stick to the native options: Why not use the Membership Provider? The ASP.Net membership provider can handle all of this for you. You can specify which groups can access which pages/directories using web.config files no sweat.
Check out these links for further guidance on implementing the Active Directory membership provider:
http://msdn.microsoft.com/en-us/library/system.web.security.activedirectorymembershipprovider.aspx
http://blogs.msdn.com/b/gduthie/archive/2005/08/17/452905.aspx
This XML shows how you can configure your web.config, once you are using the membership provider, so that it allows/denies permission to files and folders (I got this from http://support.microsoft.com/kb/316871):
<configuration>
<system.web>
<authentication mode="Forms" >
<forms loginUrl="login.aspx" name=".ASPNETAUTH" protection="None" path="/" timeout="20" >
</forms>
</authentication>
<!-- This section denies access to all files in this application except for those that you have not explicitly specified by using another setting. -->
<authorization>
<deny users="?" />
</authorization>
</system.web>
<!-- This section gives the unauthenticated user access to the Default1.aspx page only. It is located in the same folder as this configuration file. -->
<location path="default1.aspx">
<system.web>
<authorization>
<allow users ="*" />
</authorization>
</system.web>
</location>
<!-- This section gives the unauthenticated user access to all of the files that are stored in the Subdir1 folder. -->
<location path="subdir1">
<system.web>
<authorization>
<allow users ="*" />
</authorization>
</system.web>
</location>
</configuration>
I ended up rolling my own security class for checking to see if the currently logged in Active Directory user has access.
I used the GroupPrincipal.GetMembers function in the System.DirectoryServices.AccountManagement namespace. This overloadedd method which takes a boolean value can be used to search for users recursively (satisfying my groups-within-groups issue).
The security class is a Singleton, and the list allowed active directory users is stored inside the Singleton to keep this access check fast. I chose a Singleton to ensure that there was only 1 copy of this list on the server. I stored the list of allowed users as a SortedDictionary, which increased look-up speed greatly.
When a user who does not exist tries to access the site, the original user lookup will come back negative. At this point, the security class refreshes the users list, saving the timestamp of this refresh to the list of allowed users. The method endures that this refresh is done at most once every 10 minutes to prevent users from hammering the site (and keeping the site responsive for other users).

Enforcing web.config authorization entries

Ultimate goal is to provide protection against programming mistakes. I want to make sure that every page in a portion of my web application has a role specified like below. Ideally I would like to programatically check all requests coming in ( think IHttpModule ) and make sure that the page being requested has a role specified.
I can't seem to find how to get programatic access to the allowed roles.
<location path="foo.aspx">
<system.web>
<authorization>
<allow roles="modifier"/>
</authorization>
</system.web>
</location>
make a deny * in the root, so every page is not allowed, until it is explicitly activated....
Stumbled across this AuthorizationRuleCollection.
From MSDN, I've not tried it as I solved my problem using a tecnique similar to the AuthorizeAttribute in the MVC framework.
System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("/aspnetTest");
AuthorizationSection authorizationSection = (AuthorizationSection)configuration.GetSection("system.web/authorization");

Resources