Understanding IIS 7.0 URL Authorization
by Saad Ladki
Authorization was difficult in previous versions of IIS. Because IIS only worked with Windows identities, you had to go to the file system and set Access Control Lists on files and directories. This was tedious because the ACL UI is complex and authorization rules do not copy very well from machine to machine.
IIS 7.0 and above uses URL Authorization. It allows you to put authorization rules on the actual URL instead of the underlying file system resource. Additionally, the IIS URL Authorization configuration is stored in web.config files-- you can distribute authorization rules with the application content. The following walkthrough introduces you to the IIS URL Authorization feature in Windows Server® 2008 Beta 3 and Windows Vista Service Pack 1.
This walkthrough requires installing the following IIS above features on top of the default install:
- "ASP.NET" under "Internet Information Services" – "World Wide Web Services" – "Application Development Features"
- "URL Authorization" under "Internet Information Services" –" World Wide Web Services" – "Security"
Let's simulate a scenario where you have a secure directory that only Alice, Bob and the Administrators group can access. Within this directory we have a file called bobsSecret.aspx that only Bob is supposed to access.
For this scenario we need three users: Alice, Bob and Fred. We also need a new group called BobAndFriends in which Alice and Bob are members. Create the three accounts and the group via the Windows User Manager or by starting an elevated command prompt and enter the following commands
net user Alice <password_of_your_choice> /add net user Bob <password_of_your_choice> /add net user Fred <password_of_your_choice> /add net localgroup BobAndFriends /add net localgroup BobAndFriends Alice /add net localgroup BobAndFriends Bob /add
Open Explorer and go into the
Create a directory called "secure".
Change into the "secure" directory and create a new file called "default.aspx". You can do this with notepad or any other text editor.
Paste the following code into the default.aspx page:
<%@Language="C#"%> <% string currentUser = Request.ServerVariables["LOGON_USER"]; if (currentUser == "") currentUser = "anonymous"; Response.Write("<b>Current User:</b> " + currentUser); %>
Create another file called bobsSecret.aspx and paste the following code into it:
<%@Language="C#"%> <% string currentUser = Request.ServerVariables["LOGON_USER"]; if (currentUser == "") currentUser = "anonymous"; Response.Write("<b>Current User:</b> " + currentUser); Response.Write(" <b>My secret:</b> I used Apache before I discovered IIS7.</b> "); %>
Now see if the two web pages work by requesting
Authentication answers the question "who" wants to have access. Authorization answers "if" the authenticated "who" actually gets access. So, before experimenting around with URL authorization, we must enable authentication because without knowing "who" wants to have access, we cannot answer the "if".
Start INETMGR by typing INETMGR in the "Start Search" menu.
Open the machine node in the left tree view, then open the "Default Web Site" node and select the "secure" directory.
Double click "Authentication."
Disable "Anonymous Authentication" and enable "Basic Authentication."
http://localhost/secure/bobsSecret.aspxagain. You will get prompted for credentials. Enter "Alice" as username and her password. You will be authenticated as "Alice".
If you use Internet Explorer, you may to hit Ctrl+F5 so that Internet Explorer refreshes the cached version of the ASP.NET page.
Configuring URL Authorization
Now secure the two pages so that only Alice and Bob have access:
Double click the "secure" web directory again and select "Authorization Rules".
Remove the "Allow All Users" rule.
Click "Add Allow Rule" and select the "Specified roles or user groups:" radio button and add "BobAndFriends" and click the "OK" button.
Close all Internet Explorer windows because Internet Explorer caches the credentials that you entered in the previous step.
Open Internet Explorer and try to access the page using Fred's credentials. You do not get access.
Now try Bob's credentials or Alice's credentials. You get access.
Configuring URL Authorization for a single web page
Now we still have the problem left that Alice can still access BobsSecret.aspx. Here is how you fix it:
Double click the "Secure" web directory again and select "Content View" at the bottom of the page.
You will see a list of files in the secure folder namely "default.aspx" and "bobsSecret.aspx".
Right click on bobsSecret.aspx and select "Feature View"
Now you are making only changes for the bobsSecret.aspx page as indicated in the statusbar.
Select "Authorization Rules" again. You see the inherited settings, i.e. the BobsAndFriends group is allowed to access bobsSecret.aspx.
Remove the "BobsAndFriends" rule.
Now click "Add Allow Rule…"
Click the "Specified users:" radio button, enter "Bob" and click "OK".
Close all Internet Explorer windows and request
Only by entering Bob's credentials will you get access.
URL Authorization Advanced Topics
The next paragraphs show some advanced URL Authorization topics.
You do not have to use the User Interface to specify URL Authorization settings. You can specify URL Authorization rules directly in your web.config file. The IIS <authorization> configuration section is delegated by default--you can distribute authorization rules together with web content. Below, see how the
%systemdrive%\inetpub\wwwroot\secure\web.config file looks after following this walkthrough:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <security> <authorization> <remove users="*" roles="" verbs="" /> <add accessType="Allow" roles="BobAndFriends" /> </authorization> </security> </system.webServer> <location path="bobsSecret.aspx"> <system.webServer> <security> <authorization> <remove users="" roles="BobAndFriends" verbs="" /> <add accessType="Allow" users="Bob" /> </authorization> </security> </system.webServer> </location> </configuration>
Differences Between ASP.NET URL Authorization and IIS URL Authorization
There are small but important differences between ASP.NET UrlAuthorization and IIS URL Authorization. Both modules can be installed via the IIS Setup. IIS URL Authorization installs when you install the "URL Authorization" feature in the IIS Setup User Interface:
ASP.NET Url Authorization is installed when you install ASP.NET on top of IIS. If you are an ASP.NET expert, you recall that ASP.NET UrlAuthorization is implemented in the System.Web.Security.UrlAuthorizationModule module. The corresponding configuration section is system.web/authorization. Here is the configuration entry.
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" preCondition="managedHandler" />
The IIS URL Authorization module is implemented in the global module urlauthz.dll.
<add name="UrlAuthorizationModule" image="%windir%\System32\inetsrv\urlauthz.dll" />
It is important to keep in mind that the managedHandler precondition is on the ASP.NET UrlAuthorization module. The precondition tells you that the URL authorization module is invoked only when the code that handles the request is mapped to managed code, typically an .aspx or .asmx page. IIS URL Authorization, on the other hand, applies to all content. You can remove the managedHandler precondition from the ASP.NET Url Authorization module. It is there to prevent a performance penalty you have to pay when every request (such as a request to .html or .jpg pages) would have to go through managed code.
There are also differences in the order in which IIS and the two URL authorization modules evaluate authorization rules. ASP.NET URL Authorization is developer-focused and developers have full control over which rules they set. IIS URL Authorization keeps the Administrator in mind and tries to make sure that developers cannot override the rules an Administrator sets.
Suppose the administrator wants to ensure that all users of a particular site must be authenticated. To do this is, set the following configuration on the site root:
<authorization lockElements="clear"> <add accessType="Deny" users="?" /> </authorization>
This configuration denies access to anonymous users (? = anonymous users, * = all users). With the lockElements="clear", you ensure that no one on a lower level can clear the inheritance of this setting. Your setting would be inherited to all applications and virtual directories of this site. It comes to a lock violation when you try to use the <clear/> statement at a lower level.
For more information on configuration locking, see How to: Lock ASP.NET Configuration Settings.
You can also lock the clear element in ASP.NET Url Authorization. The problem is that ASP.NET URL Authorization evaluates authorization rules from the bottom up, i.e. it first evaluates rules in the current web.config file before it evaluates parent rules. As soon as a match is found, access is granted or denied. In the above example, you can still grant access to anonymous users by specifying <add users="?"/> as an authorization rule in the secure web.config file. Because it gets evaluated first, anonymous users would be granted access.
The IIS URL Authorization module evaluates deny rules first. Because you deny access to anonymous users, you cannot simply override that rule. The other big difference is that parent rules are evaluated first. This means that if you deny access for Fred at a higher level, you can't allow access to Fred on a lower level.
|Difference||ASP.NET URL Authorization Behavior||IIS URL Authorization Behavior|
|Rule evaluation||Order: a) Lower level first going up to the parent b) Order of appearance in rule collection||Order: a) Deny rules get evaluated first starting at the parent b) Allow rules starting at the parent. c) Order of appearance in rule collection|
|IIS User Interface||No IIS User Interface||"Authorization Rules" User Interface|
|Content||Applies only to content that is mapped to a managed handler (can be turned off via managedHandler precondition)||Applies to all content|
Using Domain Accounts and Groups
You must specify domain accounts and groups using the following:
<domainname or username>\<user>
This example uses the machinename, assuming our accounts were created on machine iis7test:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <security> <authorization> <remove users="*" roles="" verbs="" /> <add accessType="Allow" roles="iis7test\BobAndFriends" /> </authorization> </security> </system.webServer> <location path="bobsSecret.aspx"> <system.webServer> <security> <authorization> <remove users="" roles="iis7test\BobAndFriends" verbs="" /> <add accessType="Allow" users="iis7test\Bob" /> </authorization> </security> </system.webServer> </location> </configuration>
Using Non-Windows Identities
URL Authorization is not only for Windows identities. It works well for non-Windows, too. Use it together with ASP.NET Membership and Roles and for custom identities, in case you write your own authentication module.
URL Authorization is a powerful new way to specify authorization rules for web applications. Now you can specify rules in XML without using Windows Access Control Lists any longer.