Sun Java Solaris Communities My SDN Account Join SDN
 
Article

Sun and Microsoft Interoperate for Web Authentication, Part 1

 
 
By Pat Patterson and Marina Sum, December 4, 2006; updated: October 9, 2007  

Note: See also Part 2: Sun Java System Access Manager and SharePoint Portal Server 2003 and Part 3: Sun Java System Access Manager and Microsoft Outlook Web Access for Exchange Server 2003.

This article, the first in a three-part series, elaborates on how to integrate Active Server Pages (ASP) and ASP.NET applications into a single sign-on (SSO) environment with Sun Java System Access Manager (henceforth, Access Manager) and the Sun Java System Access Manager Policy Agent (henceforth, the Policy Agent) for Microsoft Internet Information Server (IIS). Specifically, this article does the following:

  • Discusses interoperability between Access Manager and Microsoft technologies.

  • Examines the interplay among Access Manager, the Policy Agent, IIS, and .NET applications and describes how to integrate Access Manager into a .NET environment and pre-.NET ASP applications.

  • Explains how to configure IIS for a deeper integration so that the IIS thread can "impersonate" users to gain access to resources according to Windows' Access Control Lists (ACLs).

This article assumes basic familiarity with Access Manager and IIS.

Note: The Policy Agent 2.1 is available for IIS 5.0 (Windows 2000); the Policy Agent 2.1 and 2.2, for IIS 6.0 (Windows 2003). The procedures in this article are based on Policy Agent 2.2-01 for IIS 6.0.

Contents
 
Authentication in IIS
Authorization by IIS
Deployment of the Policy Agent 2.2 for IIS 6.0
Conclusion
Preview of Upcoming Papers
Acknowledgment
References
 
Authentication in IIS

First, let's look at how authentication and authorization work by default in IIS. This section discusses the function of Basic Authentication, which applies to the widest variety of browsers and topologies and which you can swap out for authentication with Access Manager.

Anonymous Access

How does IIS handle anonymous access? Find out with these simple steps:

  1. Save the following script into a Web site's root docs directory—by default, c:\inetpub\wwwroot— as welcome.asp and then copy welcome.asp as welcome.aspx in the same directory.

    <% @Language="VBScript" %>
    <%
    Dim name
    name = Request.ServerVariables("HTTP_COMMON_NAME")
    %>
    <html>
      <head>
        <title>Welcome, <%= name %></title>
      </head>
      <body>
        <h3>Welcome, <%= name %>!</h3>
        <table border="1">
          <tr>
    	<td>REMOTE_USER</td>
    	<td><%= Request.ServerVariables("REMOTE_USER") %></td>
          </tr>
          <tr>
    	<td>LOGON_USER</td>
    	<td><%= Request.ServerVariables("LOGON_USER") %></td>
          </tr>
          <tr>
    	<td>AUTH_USER</td>
    	<td><%= Request.ServerVariables("AUTH_USER") %></td>
          </tr>
          <tr>
    	<td>HTTP_COMMON_NAME</td>
    	<td><%= Request.ServerVariables("HTTP_COMMON_NAME") %></td>
          </tr>
        </table>
      </body>
    </html>
    
     
    This script displays server variables that pertain to the authenticated user. The user's unique ID is key to personalization, a process that generates personalized Web sites, in which users can view and edit their own data only.

  2. Ensure that both classic ASP and ASP.NET are enabled in IIS by opening IIS Manager and clicking Web Service Extensions under Internet Information Services.

    You can view or change the status of the ASP pages and ASP.NET Web extensions in the right pane.

    In the absence of authentication, both welcome.asp and welcome.aspx issue the same response, with a blank in the user-name spot after the welcome greeting:

    http://win2k3-iis/welcome.asp
    Welcome, !
    
    REMOTE_USER
    LOGON_USER
    AUTH_USER
    HTTP_COMMON_NAME
    
     
    There being no authenticated user, none of the request variables as listed are set by IIS. The Microsoft support page on this subject explains why.

    The HTTP client cannot set ("spoof") those variables either. For example, even if you issue a spoofed request with wget

    wget --no-proxy --header='LOGON_USER: pat' http://win2k3-iis/welcome.aspx
    
     
    —the server still sends the same response, a testament that the ASP script does not see the LOGON_USER value sent by the client.
Basic Authentication

Now let's authenticate the user with one of the IIS built-in mechanisms. Do the following:

  1. In IIS Manager, right-click the site name and choose Properties from the context menu.

    The Default Web Site Properties pane is displayed.

  2. Click the Directory Security tab and then the Edit button under Authentication and access control.

    The Authentication Methods pane is displayed.

  3. Deselect Enable Anonymous Access and select Basic Authentication. Afterwards, specify the default domain and realm values, as appropriate, for your system.

As a test, log in as the Windows user bilbo.

The classic ASP script responds, showing three variables set to the user name.

http://win2k3-iis/welcome.asp
Welcome, !

REMOTE_USER	bilbo
LOGON_USER	bilbo
AUTH_USER	bilbo
HTTP_COMMON_NAME
 

In contrast, ASP.NET returns different values for the variables, showing LOGON_USER set to the user name you specified, and REMOTE_USER and AUTH_USER to your domain login.

http://win2k3-iis/welcome.aspx
Welcome, !

REMOTE_USER	MYDOMAIN\bilbo
LOGON_USER	bilbo
AUTH_USER	MYDOMAIN\bilbo
HTTP_COMMON_NAME
 

For definitions of those variables, see the ASP.NET documentation in question.

In both cases, the HTTP_COMMON_NAME variable is not set. You'll find out later in this article how the Policy Agent handles that setting.

Authorization by IIS

This section describes how IIS authorizes users to access resources by means of the two authorization mechanisms in ASP.NET: File Authorization and URL Authorization.

File Authorization

To secure files against unauthorized access, you can use Windows' built-in ACL mechanism. In the example below, you set ACLs on a file so that only one user can read it. After that user is logged in, IIS runs a script to retrieve the content of the file.

Do the following:

  1. Create two scripts to accommodate the difference in the programming model between classic ASP and ASP.NET. First, the classic ASP version (bilbo.asp):

    % @Language="VBScript" %>
    <html>
      <head>
        <title>bilbo's secret file</title>
      </head>
      <body>
        <h3>bilbo's secret file</h3>
        <p>
    <%
        Err.Clear
        On Error Resume Next
    
        Dim fso
        Set fso = CreateObject("Scripting.FileSystemObject")
    
        Dim fileName
        fileName = Server.MapPath("bilbo.txt")
    
        Dim file
        Set file = fso.OpenTextFile(fileName)
        If Err.Number = 0 Then
          Response.Write(file.ReadAll)
        Else
          Response.Write("Sorry, " + Request.ServerVariables("LOGON_USER") + ", I
    can't show you the file.")
        End If
    
        On Error GoTo 0
    %>
        </p>
      </body>
    </html>
    
     
    Second, the ASP.NET version (bilbo.aspx):

    <%@ Import Namespace="System.IO" %>
    <%@ Language="VBScript" %>
    <html>
      <head>
        <title>bilbo's secret file</title>
      </head>
      <body>
        <h3>bilbo's secret file</h3>
        <p>
    <%
        Try
    
          Dim fileName as String = Server.MapPath("bilbo.txt")
    
          Dim reader as StreamReader
          reader = File.OpenText(fileName)
    
          Response.Write( reader.ReadToEnd() )
    
          reader.Close()
        Catch uae as UnauthorizedAccessException
    
          ' Environment.UserName tells us the identity associated with the
          ' IIS process as far as the rest of Windows is concerned
          Response.Write ("Sorry, " +
    System.Security.Principal.WindowsIdentity.GetCurrent().Name + ", I can't show you the file.")
        End Try
    %>
        </p>
      </body>
    </html>
    
     
  2. Create a test file (bilbo.txt), as follows, to be read by the two preceding scripts.

    One identity to rule them all and, in the darkness, bind them.
    
     
  3. Place all three files in a convenient place in the IIS document tree, for example, the document root (c:\inetpub\wwwroot by default).

  4. Make bilbo.txt file readable only by bilbo.

    1. Log in as bilbo or a user with administrator privileges.

    2. b. Right-click bilbo.txt and choose Properties from the context menu.

      The bilbo.txt Properties pane is displayed.

    3. Click the Security tab and then click Advanced.

      The Advanced Security Settings pane for bilbo.txt is displayed.

    4. Deselect Allow inheritable permissions.

      A confirmation prompt is displayed.

    5. Click Remove.

    6. Click OK in the Advanced Security Settings pane.

  5. Add bilbo in the security settings: Click Add, type bilbo as the object name, and click OK.

    The bilbo.txt Properties pane is again displayed.

  6. Under Permissions for Bilbo Baggins, select Read and deselect all the other permissions. Click OK.

Finally, set IIS back to anonymous access. Do the following:

  1. In IIS Manager, right-click the site name and choose Properties from the context menu.

    The Default Web Site Properties pane is displayed.

  2. Click the Directory Security tab and then the Edit button under Authentication and access control.

    The Authentication Methods pane is displayed.

  3. Select Enable anonymous access and deselect Basic authentication.

    Given the permissions now set for bilbo.txt, both the bilbo.asp and bilbo.aspx scripts report that the file is inaccessible. Here's the output:

    http://win2k3-iis/bilbo.asp
    bilbo's secret file
    
    Sorry, I can't show you the file.
    
     
    http://win2k3-iis/bilbo.aspx
    bilbo's secret file
    
    Sorry, WIN2K3-IIS\IUSR_WIN2K3-IIS, I can't show you the file.
    
     
    The ASP.NET output shows that IIS is executing in the context of a system identity—WIN2K3-IIS\IUSR_WIN2K3-IIS. That is a relatively unprivileged account specifically for use by IIS on behalf of unauthorized users.
Basic Authentication

Next, configure IIS for basic authentication:

  1. In IIS Manager, right-click the site name and choose Properties from the context menu.

  2. Click the Directory Security tab and then the Edit button under Authentication and access control.

    The Authentication Methods pane is displayed.

  3. Deselect Enable Anonymous Access and select Basic Authentication.

As a test, access each of bilbo's two private pages at http://win2k3-iis/bilbo.asp and http://http://win2k3-iis/bilbo.aspx. The correct results are as follows.

Classic ASP enables you to read bilbo's secret file, as shown by this output:

http://win2k3-iis/bilbo.asp
bilbo's secret file

One identity to rule them all and, in the darkness, bind them.
 

ASP.NET does not, as shown by this output:

http://win2k3-iis/bilbo.aspx
bilbo's secret file

Sorry, NT AUTHORITY\NETWORK SERVICE, I can't show you the file.
 

Why? In the classic ASP model, IIS impersonates, by default, the authenticated user, hence both IIS and bilbo.asp can access bilbo.txt. Not so with ASP.NET: Even after user authentication, IIS runs in the context of a relatively unprivileged system account (NT AUTHORITY\NETWORK SERVICE in the case of IIS 6.0), hence the access denial.

As a resolution, configure ASP.NET to impersonate users through the web.config file. Create that file, as follows, in a directory of your choice, for example, the IIS root documents folder (wwwroot).

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <identity impersonate="true" />
  </system.web>
</configuration>
 

Now bilbo.aspx shows you the file content:

http://win2k3-iis/bilbo.aspx
bilbo's secret file

One identity to rule them all and, in the darkness, bind them.
 
URL Authorization

ASP.NET includes a mechanism, as follows, to control access to ASP.NET-managed resources with the web.config file.

<authorization>
  <[allow|deny] users roles verbs />
</authorization>
 

To configure authorization, place an <authorization> element in the root web.config file for a site, as in the following example, which enables access to only the resources in this directory.

<authorization>
  <allow users="bilbo"/>
  <deny users="*"/>
</authorization>
 

<authorization> can contain any number of allow and deny elements, each of which specifies a set of principals and HTTP actions. For details, see the section ASP.NET Authorization in the documentation.

Alternatively, create a web.config file to define the settings for a particular directory. In this example, take the preceding step so that all the related files reside in one location.

  1. Under wwwroot, create a bilbo directory with the default.aspx file, as follows.

    <html>
    <head>
    Only bilbo can see this!
    </head>
    <body>
    <p>
    Reminder: Throw ring in Mount Doom!
    </p>
    </body>
    </html>
    
     
    Note: By default, IIS applies authorization to only the file types that are managed by ASP.NET, such as .aspx. If you named the preceding file default.htm, for example, IIS does not perform the authorization.

  2. Edit wwwroot\web.config and add the boldfaced lines in the following code segment to ensure that only bilbo can read the new script.

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.web>
        <identity impersonate="true" />
      </system.web>
      <location path="bilbo">
        <system.web>
          <authorization>
    	<allow users="mydomain\bilbo" />
    	<deny users="*" />
          </authorization>
        </system.web>
      </location>
    </configuration>
    
     

Now, access http://win2k3-iis/bilbo as bilbo. The output depicts successful authorization.

Reminder: Throw ring in Mount Doom!
 

If you are not authenticated as bilbo, then, depending on the browser, IIS repeatedly prompts for reentry of credentials. After three failed attempts, IIS displays this message:

Server Error in '/' Application.
Access is denied.
Description: An error occurred while accessing the resources
required to serve this request. The server may not be configured
for access to the requested URL.

Error message 401.2.: Unauthorized: Logon failed due to server
configuration. Verify that you have permission to view this
directory or page based on the credentials you supplied and the
authentication methods enabled on the Web server. Contact the Web
server's administrator for additional assistance.
 

The remainder of this article describes how to configure equivalent policies in Access Manager. In addition, you'll learn how to integrate ASP.NET's URL authorization with Access Manager when migration to Access Manager policies is impractical.

Deployment of the Policy Agent 2.2 for IIS 6.0

In its simplest configuration, the Policy Agent protects resources—in this context, a set of URLs on IIS—from unauthorized access. When a user attempts to access a protected resource, the Policy Agent displays a login page and, assuming a subsequent authentication of that user, consults Access Manager's policies to determine whether to grant access to the requested resource.

As an Internet Server API (ISAPI) application, the Policy Agent is deployed as a wildcard application that maps to a Web site. When deployed, the Policy Agent intercepts the requests for accessing resources on that site and performs authentication and policy evaluation tasks. If all the policy conditions are met, the Policy Agent grants access to the resources.

You configure the Policy Agent for one site per application pool. Therefore, to configure multiple sites on one machine, you organize them into multiple application pools.

Furthermore, the Policy Agent enforces URL policies and can copy user profile attributes, such as user name, common name, and so forth, into HTTP header variables, thus enabling IIS applications to locate the authenticated user's identity.

Benefits

Access Manager and the Policy Agent offer numerous benefits over managing authentication and authorization at the Web-server level, as follows:

  • Authentication is centralized in Access Manager. You can configure Access Manager to use any of a wide range of authentication mechanisms, from user name and password to certificates, also to work with smart cards and hardware tokens. You can even extend Access Manager with custom-built mechanisms.

  • Authorization is centralized into a set of policies that apply to the entire enterprise. Policies are much more sophisticated than the common ones like "Allow access to bilbo" and "Deny access to users with the sales role." For example, you can include these conditions:

    • A specific mechanism for authentication, such as "This page requires smart-card authentication."

    • Times and dates, such as:
      "Allow access to regular users from 9 a.m.-5 p.m., Monday through Friday."
      "Allow access to administrators, 24/7."

    • IP address ranges that are criteria for access, such as "Deny access to users logging in through the VPN."

  • The Policy Agents are available for a wide range of Web containers and applications. Those containers and applications range from Sun Java System Web Server and Sun Java System Application Server to SAP Enterprise Portal and Lotus Domino (see the Policy Agent download site). You can even use Access Manager's C and Java SDKs to factor out authentication and authorization from applications.

  • SSO is available across all protected resources. That's by virtue of Access Manager's federation capabilities that extend SSO across enterprises through the SAML 2.0 and Liberty standards.
Installation and Configuration of the Policy Agent for IIS
  1. Download Policy Agent 2.2-01 for IIS 6.0.

  2. Log in to the Access Manager console and create a policy that enables all authenticated users to access all the URLs on your IIS server, that is, http://win2k3-iis/*.

  3. Edit the AMAgent.properties configuration file: Set com.sun.am.policy.agents.config.profile.attribute.fetch.mode to HTTP_HEADER so that the Policy Agent inserts the user attributes in the HTTP request as HTTP headers.

    The property com.sun.am.policy.agents.config.profile.attribute.map tells the Policy Agent which attributes to insert and how to map their names.

  4. Restart the application pool and the Web site.

  5. In Access Manager, create a user whose ID (uid) corresponds to the user's Windows user name.

    This exercise relies on simple correspondence between the IDs on the two systems. The com.sun.am.policy.am.userid.param property tells the Policy Agent which Access Manager session property to map to the Windows user name.
No IIS Authentication

To configure anonymous access by IIS, set IIS back to anonymous access. Follow these steps:

  1. In IIS Manager, right-click the site name and choose Properties from the context menu.

    The Default Web Site Properties pane is displayed.

  2. Click the Directory Security tab and then the Edit button under Authentication and access control.

    The Authentication Methods pane is displayed.

  3. Select Enable Anonymous Access and deselect Basic Authentication.
Classic ASP Behavior

Even with the above setting, the Policy Agent still intercepts any attempt to access the welcome scripts and redirects the user's browser to Access Manager's login page. After logging in as the Access Manager user bilbo, you see this output from welcome.asp:

http://win2k3-iis/welcome.asp
Welcome, Bilbo Baggins!

REMOTE_USER bilbo
LOGON_USER bilbo
AUTH_USER bilbo
HTTP_COMMON_NAME Bilbo Baggins
 

The values of the first three variables are identical to those that are output by the script in basic authentication. For HTTP_COMMON_NAME, Access Manager produces the output from a retrieval of the cn attribute from the user's LDAP profile as a result of this protocol:

The com.sun.am.policy.agents.config.profile.attribute.map property in the AMAgent.properties file defines the mapping from cn to common-name, which Access Manager maps again to HTTP_COMMON_NAME.

You can direct Access Manager and the Policy Agent to retrieve other attributes from the user's LDAP profile in the same manner.

ASP.NET Behavior

In contrast, welcome.aspx running on ASP.NET outputs the following:

http://win2k3-iis/welcome.aspx
Welcome, Bilbo Baggins!

REMOTE_USER		WIN2K3-IIS\IUSR_WIN2K3-IIS
LOGON_USER		bilbo
AUTH_USER		WIN2K3-IIS\IUSR_WIN2K3-IIS
HTTP_COMMON_NAME	Bilbo Baggins
 

Here, IIS sets the REMOTE_USER and AUTH_USER variables to WIN2K3-IIS\IUSR_WIN2K3-IIS, the default anonymous system user for IIS. Even though the Policy Agent has authenticated the user as bilbo and set LOGON_USER at the system level, IIS still considers the request to be anonymous.

Access Denials

Now, when you access bilbo's secret file with classic ASP, you receive a denial:

http://win2k3-iis/bilbo.asp
bilbo's secret file

Sorry, I can't show you the file.
 

Same with ASP.NET:

http://win2k3-iis/bilbo.aspx
bilbo's secret file

Sorry, WIN2K3-IIS\IUSR_WIN2K3-IIS, I can't show you the file.
 

In both cases, IIS cannot access the file. Even though the Policy Agent has authenticated the user, the IIS File Authorization mechanism still considers the access to be anonymous. See the next section for a resolution.

Configuration of the Policy Agent for HTTP Basic Authentication

With the Policy Agent 2.2 for IIS 6.0, you can configure an ISAPI filter for basic authentication. Simply install the ISAPI filter into IIS and configure the Access Manager postauthentication plug-in, as described in Appendix A in the Sun Java System Access Manager Policy Agent 2.2 Guide for Microsoft Internet Information Services 6.0. Finally, reconfigure IIS back to basic authentication.

Afterwards, to access the welcome scripts, you need only authenticate to Access Manager as bilbo, as shown in the following output, with no output for basic authentication.

http://win2k3-iis/welcome.asp
Welcome, Bilbo Baggins!

REMOTE_USER	  bilbo
LOGON_USER	  bilbo
AUTH_USER	  bilbo
HTTP_COMMON_NAME  Bilbo Baggins
 
http://win2k3-iis/welcome.aspx
Welcome, Bilbo Baggins!

REMOTE_USER	  MYDOMAIN\bilbo
LOGON_USER	  bilbo
AUTH_USER	  MYDOMAIN\bilbo
HTTP_COMMON_NAME  Bilbo Baggins
 

Note that AUTH_USER and REMOTE_USER are set to MYDOMAIN\bilbo, not the local IIS user WIN2K3-IIS\IUSR_WIN2K3-IIS.

Tests

The output for bilbo's secret file, as accessed by bilbo.asp and bilbo.aspx, is identical.

http://win2k3-iis/bilbo.asp
bilbo's secret file

One identity to rule them all and, in the darkness, bind them.
 
http://win2k3-iis/bilbo.aspx
bilbo's secret file

One identity to rule them all and, in the darkness, bind them.
 

In other words, success in file access as bilbo!

Log in as another user, say, frodo, and you'll see these two instances of the welcome message, as you would expect:

http://win2k3-iis/welcome.asp
Welcome, Frodo Baggins!

REMOTE_USER		frodo
LOGON_USER		frodo
AUTH_USER		frodo
HTTP_COMMON_NAME	Frodo Baggins
 
http://win2k3-iis/welcome.aspx
Welcome, Bilbo Baggins!

REMOTE_USER MYDOMAIN\frodo
LOGON_USER frodo
AUTH_USER MYDOMAIN\frodo
HTTP_COMMON_NAME Frodo Baggins
 

How about file access? No go, of course:

http://win2k3-iis/bilbo.asp
bilbo's secret file

Sorry, frodo, I can't show you the file.
 
http://win2k3-iis/bilbo.aspx
bilbo's secret file

Sorry, MYDOMAIN\frodo, I can't show you the file.
 

So, with IIS configured for basic authentication and impersonation, the Policy Agent integrates IIS into an Access Manager infrastructure—down to accessing files on the disk.

URL Authorization

To see the behavior in URL authorization subsequent to the preceding configuration, first access the script in bilbo's directory as bilbo. Here is the output, which attests to success:

http://win2k3-iis/bilbo
Reminder: throw ring in Mount Doom!
 

Next, log in as frodo. You'll see the same response as described before, that is, a prompt to reenter your credentials. After three failed attempts, IIS displays this error message:

Server Error in '/' Application.
Access is denied.
Description: An error occurred while accessing the resources
required to serve this request. The server may not be configured
for access to the requested URL.

Error message 401.2.: Unauthorized: Logon failed due to server
configuration. Verify that you have permission to view this
directory or page based on the credentials you supplied and the
authentication methods enabled on the Web server. Contact the Web
server's administrator for additional assistance.
 
Conclusion

For .NET Web applications that rely on an IIS authentication mechanism, you can reconfigure IIS to have the Policy Agent administer SSO and access control to those applications. For applications that perform their own authentication, for example, against flat files or databases, simply delete the authentication code and adopt the LOGON_USER server variable instead.

Preview of Upcoming Papers

Future articles will show you how to integrate Access Manager with SharePoint Portal Server 2003 and Outlook Web Access in Microsoft Exchange 2003.

Acknowledgment

We gratefully acknowledge the contribution of Stefan Schakow of Microsoft's ASP.NET team, who reviewed this article in detail and suggested a number of enhancements before its publication. Any errors are, of course, the responsibility of the authors.

References
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.
Pat PattersonPat Patterson, a technical architect at Sun, has been working on security and identity management since 1997, when he joined Trustbase Ltd., a software development company in London, England. When Sun acquired Trustbase in 2000, Pat became an engineering manager in secure Web services at Sun. After a four-year stint in product management, he returned to engineering early in 2005, focusing on federation, on identity-enabled Web services, and on OpenSSO, Sun's open-source, Access Manager-based project. Pat's blog centers on identity-related topics.
 
Marina SumMarina Sum is a staff writer for Sun Developer Network. She has been writing for Sun since 1989, mostly in the technical arena. Marina blogs on Sun's products, technologies, events, publications, and unsung heroes.