Recipe: Enabling Windows Authentication within an Intranet ASP.NET Web application
Problem:
You are building an Intranet web application for your organization, and you want to authenticate the users visiting your site. Specifically, you want to ensure that they are logged in using a valid Windows account on the network, and you want to be able to retrieve each incoming user's Windows account name and Windows group membership within your application code on the server.
Discussion:
Authentication is the process of identifying and validating the identity of a client accessing an application. Put more simply -- it is the process of identifying “who” the end-user is when they visit a website.
Authentication is typically used in combination with Authorization -- which is the process of figuring out whether the authenticated user has permissions to access a particular page/resource or to perform some action. For example, when an end-user in a browser tries to access a page, ASP.NET might authenticate the user as “Scott”, and would then run through the configured authorization rules for the requested page to figure out whether “Scott” has permission to access it.
ASP.NET supports multiple ways to authenticate browser users visiting a web application, and implements a flexible set of ways to authorize which permissions they have within the application.
For Internet web applications, the most common authentication scenario to use it called Forms Authentication. Forms Authentication enables a developer to provide a standard HTML login form within their application, and then validate the username/password an end-user submits against a database or other credential store. Assuming the username/password combination is correct, the developer can then ask ASP.NET to issue an encrypted HTTP cookie to identify and track the user.
For Intranet web applications, the most common authentication scenario to use is called Windows Authentication. Windows Authentication avoids the need to create a login form within an application, and does not require end-users to manually enter their username/password credentials to login to the application. Instead, ASP.NET and IIS can automatically retrieve and validate the Windows username of the end-user visiting the site in a secure way. The benefit of this approach is that it improves the end-user customer experience since users don’t have to re-type their passwords, and/or maintain separate accounts. It also allows companies to re-use a common security identity system across their entire corporate networks (Windows clients, servers, file-shares, printers, and web apps).
Solution:
To enable Windows Authentication within an ASP.NET Application, you should make sure that you have “Integrated Windows Authentication” (formerly called NTLM authentication) enabled within IIS for the application you are building.
You should then add a web.config file to the root directory of your ASP.NET application that contains an <authentication> section which sets the mode to “Windows”.
You should also then add an <authorization> section to the same web.config file that denies access to “anonymous” users visiting the site. This will force ASP.NET to always authenticate the incoming browser user using Windows Authentication – and ensure that from within code on the server you can always access the username and Windows group membership of the incoming user.
The below web.config file demonstrates how to configure both steps described above:
<configuration>
<system.web>
<authentication mode="Windows" />
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</configuration>
Note that the <deny users=”?”/> directive within the <authorization> section above is what tells ASP.NET to deny access to the application to all “anonymous” users to the site (the “?” character means anonymous user). This forces Windows to authenticate the user, and ensures that the username is always available from code on the server.
Obtaining the Logged-in Username via Code
Once you follow the above configuration steps, you can easily access the logged-in username and role/group mappings for the authenticated user within ASP.NET. For example, you could use the code-snippet below within an ASP.NET page to easily obtain the username of the visiting user:
Dim username As String
username = User.Identity.Name
The code-snippet above works because there is a “User” property built-in to all ASP.NET pages and user-controls. If you want to gain access to this user data from within a regular class or business object (which doesn’t have this property provided), you can write code like below to achieve the same result:
Dim User As System.Security.Principal.IPrincipal
User = System.Web.HttpContext.Current.UserDim username As String
username = User.Identity.Name
The code above obtains the User IPrincipal object for the current request by accessing it via the static HttpContext.Current property that ASP.NET provides (this in turn uses call-context to retrieve it from the active ASP.NET worker thread). This avoids you having to pass this User object into your business classes directly, and instead allows you to access the User object from anywhere in the application.
Outputting the Logged-in Username on a Page
You can use the username string we retrieved above to programmatically output the username to a page however you want. For example, you could easily add an <asp:label> control to the page and write code like so to set it:
Label1.Text = "Welcome " & User.Identity.Name
ASP.NET 2.0 also ships with a built-in <asp:LoginName> control that you can use to declaratively output the user-name to the page:
<asp:LoginName ID="LoginName1" FormatString="Welcome {0}!" runat="server" />
This control provides an easy way to display the username within the application without having to write any code at all (note the use of the “FormatString” property on the control above – which allows you to easily specify a text mask to use with it).
Looking up Role/Group information for a User
ASP.NET provides a useful “Role Management” capability, which allows developers to map users into logical “Roles” that can then be used to better control end-user capabilities and authorization access. For example, as a developer I could create a role called “managers” for my web application, and then limit access to portions of the site to only those users within the “managers” role (note: I will be posting additional recipes in the future that discuss how to fully use the Role Management authorization and capabilities features more).
When using Windows Authentication, ASP.NET allows developers to create and populate roles from multiple sources. For example, a developer could setup the built-in ASP.NET 2.0 SqlRoleProvider to map Windows users to custom application roles that are store within a database. This approach is very useful for scenarios where there might be application-specific role mappings that don’t make sense to push into a centralized Active Directory tree/store.
ASP.NET also makes it easy to access central Windows and Active Directory group mappings from within an application as well. For example, if there is a Windows group on the Active Directory network called “DOMAIN\managers”, an ASP.NET application could lookup whether the current Windows authenticated user visiting the ASP.NET site belongs to this group by writing code like this:
If User.IsInRole("DOMAIN\managers") Then
Label1.Text = User.Identity.Name & " is a manager"
Else
Label1.Text = User.Identity.Name & " is not a manager"
End If
Note that the role/group look-up is done via the “User.IsInRole(rolename)” method that is a peer of the User.Identity.Name property.
Next Steps
Once you understand the basics above, you know how to authenticate and identify Windows users visiting your Intranet application, as well as to lookup what Windows groups and roles they belong to.
In a future Recipe we’ll walkthrough more advanced role-management scenarios, and also discuss ways to authorize and restrict access and capabilities within an ASP.NET application based on the authenticated user’s authorization rights.
Additional Discussion:
• Links to Tons of ASP.NET Security Content
• How To: Use Windows Authentication in ASP.NET 2.0
Hope this helps,
Scott