Click here to Skip to main content
Click here to Skip to main content
Articles » Web Development » ASP.NET » General » Downloads
 
Add your own
alternative version

Windows Authentication Using Form Authentication

, 1 Jul 2009 CPL
An article on "How to authenticate windows user using form authentication in ASP.NET?"
WindowsAuthenticationUsingFormAuthentication.zip
WindowsAuthenticationUsingFormAuthentication.GIF
WindowsAuthenticationUsingFormAuthentication_Demo.zip
WindowsAuthenticationUsingFormAuthentication_Demo.zip
App_Code
App_Data
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--------------------------------------------------------------------------->  
<!--                           INTRODUCTION                                

 The Code Project article submission template (HTML version)

Using this template will help us post your article sooner. To use, just 
follow the 3 easy steps below:
 
     1. Fill in the article description details
     2. Add links to your images and downloads
     3. Include the main article text

That's all there is to it! All formatting will be done by our submission
scripts and style sheets. 

-->  
<!--------------------------------------------------------------------------->  
<!--                        IGNORE THIS SECTION                            -->
<html>
<head>
<title>Windows Authentication using Form Authentication</title>
<Style>
BODY, P, TD { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt }
H2,H3,H4,H5 { color: #ff9900; font-weight: bold; }
H2 { font-size: 13pt; }
H3 { font-size: 12pt; }
H4 { font-size: 10pt; color: black; }
PRE { BACKGROUND-COLOR: #FBEDBB; FONT-FAMILY: "Courier New", Courier, mono; WHITE-SPACE: pre; }
CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; }
</style>
<link rel="stylesheet" type="text/css" href="http://www.codeproject.com/App_Themes/NetCommunity/CodeProject.css">
</head>
<body bgcolor="#FFFFFF" color=#000000>
<!--------------------------------------------------------------------------->  


<!-------------------------------     STEP 1      --------------------------->
<!--  Fill in the details (CodeProject will reformat this section for you) -->

<pre>
Title:       Windows Authentication using Form Authentication
Author:      Muhammad Akhtar Shiekh 
Email:       akhhttar@gmail.com
Member ID:   2243665
Language:    C#
Platform:    Windows, .NET 2.0 etc
Technology:  ASP.NET,
Level:       Intermediate
Description: An article on Windows Authentication using Form Authentication
Section      ASP.NET
SubSection   Security
License:     CPL
</pre>

<!-------------------------------     STEP 2      --------------------------->
<!--  Include download and sample image information.                       --> 

<ul class=download>
<li><a href="WindowsAuthenticationUsingFormAuthentication_Demo.zip">Download demo project - 6 Kb </a></li>

</ul>

<p><img src="WindowsAuthenticationUsingFormAuthentication.GIF" alt="Windows Authentication using Form Authentication" width=536 height=302></p>


<!-------------------------------     STEP 3      --------------------------->

<!--  Add the article text. Please use simple formatting (<h2>, <p> etc)   --> 



<h2>Background </h2>

<p>Last month I worked on a small assignment to authenticate windows account (Domain or Local) using form authentication. Purpose of this task was to facilitate our application users to login with any valid windows account (Instead of automatically authentication of windows logged in user).
<br />
<br />
As it was an interesting task, so I decided to share my experience with you

</p> 

<h2>Requirement</h2>
<p>Application should authenticate windows user using form authentication. So that currently logged in user shouldn�t be bound to logged-in in the application only with his windows account only. He should be able to logged-in with any valid windows account.</p>

<h2>Solution</h2>
We need to do the following steps to get the desired functionality done,
    <ol>
        
        <li>Configure Authorization and Authentication settings in web.config.</li> 
        <li>A login page and execute logic to authenticate provided credential of windows user.</li>
<li>If provided credentials are authentication in step 2, and then generate an authentication token so that user should be able to navigate into the authorized pages of your application</li>

       
    </ol>

<h3>1. Configure Authorization and Authentication settings in web.config:</h3>
<p>
We need to use Form authentication. User will enter his windows credential in the form and we will validate provided windows credential using custom logic in step 2.

<pre lang="aspnet" >
&lt;authentication mode="Forms"&gt;
	&lt;forms loginUrl="login.aspx" name=".ASPXFORMSAUTH"&gt;&lt;/forms&gt;
&lt;/authentication&gt;

</pre>
To restrict anonymous access, you need to do following authorization settings in web.config

<pre lang="aspnet">
&lt;authorization&gt;
	&lt;deny users="?"/&gt;
&lt;/authorization&gt;

</pre>
</p>

<h3>2. 	Create a login page and execute logic to authenticate provided credential of windows user:</h3>
<p>
we need to create a login page ( e.g. login.aspx) to get username and password information from user and then validate them.
We can have different options to validate windows credentials, the way I choose is 
    <b>LogonUser()</b> method of a win32 API called <b>Advapi32.dll</b>. 
<br />
<br />
The <b>LogonUser</b> function attempts to log a user on to the local computer. This method takes username, password and other information as input and return a Boolean value to indicate that either user is logged or not. If it returns true, its mean the provided username and password are correct.

To use this method in our class, we need to include following namespace 

<pre lang="cs">
using System.Runtime.InteropServices;
</pre>

And the add method declaration with DLLImport attribute (As this is method of Win32 dll which is an unmanaged DLL)

<pre lang="cs">
[DllImport("ADVAPI32.dll", EntryPoint = "LogonUserW", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
</pre>

According to the MSDN Documentation:
<br /> 
    <i><b>lpszUsername [in]</b></i>
<br /> 
A pointer to a null-terminated string that specifies the name of the user. This is the name of the user account to log on to. If you use the user principal name (UPN) format, User@DNSDomainName, the lpszDomain parameter must be NULL. 
<br />
    <i><b>lpszDomain [in, optional]</b></i>
<br />
A pointer to a null-terminated string that specifies the name of the domain or server whose account database contains the lpszUsername account. If this parameter is NULL, the user name must be specified in UPN format. If this parameter is ".", the function validates the account by using only the local account database.
<br />
l<i><b>pszPassword [in] </b></i> 
<br />
A pointer to a null-terminated string that specifies the plaintext password for the user account specified by lpszUsername. When you have finished using the password, clear the password from memory by calling the SecureZeroMemory function. For more information about protecting passwords, see Handling Passwords.
<br />
    <i><b>dwLogonType [in] 
</b></i> 
<br />
The type of logon operation to perform.
<br />
    <i><b>dwLogonProvider [in]</b></i> 
<br />
Specifies the logon provider.
<br />
    <i><b>phToken [out]</b></i> 
<br />
A pointer to a handle variable that receives a handle to a token that represents the specified user

</p>

<h3>3.	Generate an authentication token, If provided credentials are authentication in step 2:</h3>
<p>
If provided credentials are authenticated by LogonUser() method then we need to generate an authentication token so that user should be able to navigate into the authorized pages of application. <pre lang="cs" >FormsAuthentication.RedirectFromLoginPage()</pre> Or <pre lang="cs">FormsAuthentication.SetAuthCookie()</pre> can be used for this purpose.
</p>

<p>
Here is login button�s Click handler code for authentication and generating authentication token, Comment will help you to understand the code

<br />
<pre lang="cs">
protected void btnLogin_Click(object sender, EventArgs e)
    {
        string domainName = GetDomainName(txtUserName.Text); // Extract domain name form provided DomainUsername e.g Domainname\Username
        string userName = GetUsername(txtUserName.Text);  // Extract user name from provided DomainUsername e.g Domainname\Username
        IntPtr token = IntPtr.Zero;

        //userName, domainName and Password parameters are very obvious.
        //dwLogonType (3rd paramter): I used LOGON32_LOGON_INTERACTIVE, This logon type is intended for users who will be interactively using the computer, such as a user being logged on by a terminal server, remote shell, or similar process. This logon type has the additional expense of caching logon information for disconnected operations. For more details about this parameter please see http://msdn.microsoft.com/en-us/library/aa378184(VS.85).aspx
        //dwLogonProvider (4th parameter) : I used LOGON32_PROVIDER_DEFAUL, This provider use the standard logon provider for the system. The default security provider is negotiate, unless you pass NULL for the domain name and the user name is not in UPN format. In this case, the default provider is NTLM. For more details about this parameter please see http://msdn.microsoft.com/en-us/library/aa378184(VS.85).aspx
        //phToken (5th parameter): A pointer to a handle variable that receives a handle to a token that represents the specified user. We can use this handler for impersonation purpose. 
        bool result = LogonUser(userName, domainName, txtPassword.Text, 2, 0, ref token);
        if (result)
        {
            //If Sucessfully authenticated

            //When an unatuthenticated user try to visit any page of your application that is only allowed to view by authenticated users then ASP.NET automatically redirect that user to login form and add ReturnUrl query string parameter that contain the url of a page that user want to visit, So that we can redirect the user to that page after authenticated. FormsAuthentication.RedirectFromLoginPage() method not only redirect the user to that page but also genrate an authentication token for that user.
            if (string.IsNullOrEmpty(Request.QueryString["ReturnUrl"]))
            {
                FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, false);
            }
            //If ReturnUrl query string parameter is not present , then we need to genrate authentication token and redirect the user to any page ( acording to your application need). FormsAuthentication.SetAuthCookie() method will genrate Authentication token 
            else
            {
                FormsAuthentication.SetAuthCookie(txtUserName.Text, false);
                Response.Redirect("default.aspx");


            }
        }
        else
        {
            //If not authenticated then display an error message
            Response.Write("Invalid username or password.");
        }
    }

</pre>
</p>

<h2>Lets Put it All to gather:</h2>

<h4>Login.aspx</h4>
<pre lang="aspnet" >

&lt;%@ Page Language="C#" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Login" %&gt;

&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head runat="server"&gt;
    &lt;title&gt;Windows Authentication Using Form Authentication&lt;/title&gt;
    &lt;style type="text/css"&gt;
        .style1
        {
            width: 100%;
        }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id="form1" runat="server"&gt;
    &lt;div&gt;
    
        &lt;table class="style1"&gt;
            &lt;tr&gt;
                &lt;td&gt;
                    &lt;asp:Label ID="lblUserName" runat="server" Text="User Name:"&gt;&lt;/asp:Label&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &lt;asp:TextBox ID="txtUserName" runat="server"&gt;&lt;/asp:TextBox&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;
                    &lt;asp:Label ID="lblPassword" runat="server" Text="Password:"&gt;&lt;/asp:Label&gt;
                &lt;/td&gt;
                &lt;td&gt;
                    &lt;asp:TextBox ID="txtPassword" runat="server" TextMode="Password" &gt;&lt;/asp:TextBox&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td&gt;
                    &nbsp;&lt;/td&gt;
                &lt;td&gt;
                    &lt;asp:Button ID="btnLogin" runat="server" onclick="btnLogin_Click" 
                        Text="Login" /&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;/table&gt;
    
    &lt;/div&gt;
    &lt;p&gt;
        &nbsp;&lt;/p&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;


</pre>

<h4>Login.aspx.cs</h4>
<pre lang="cs">
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Runtime.InteropServices;

public partial class Login : System.Web.UI.Page
{
    [DllImport("ADVAPI32.dll", EntryPoint = "LogonUserW", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

    /// <summary>
    /// Parses the string to pull the domain name out.
    /// </summary>
    /// <param name="usernameDomain">The string to parse that must contain the domain in either the domain\username or UPN format username@domain</param>
    /// <returns>The domain name or "" if not domain is found.</returns>
    public static string GetDomainName(string usernameDomain)
    {
        if (string.IsNullOrEmpty(usernameDomain))
        {
            throw (new ArgumentException("Argument can't be null.", "usernameDomain"));
        }
        if (usernameDomain.Contains("\\"))
        {
            int index = usernameDomain.IndexOf("\\");
            return usernameDomain.Substring(0, index);
        }
        else if (usernameDomain.Contains("@"))
        {
            int index = usernameDomain.IndexOf("@");
            return usernameDomain.Substring(index + 1);
        }
        else
        {
            return "";
        }
    }

    /// <summary>
    /// Parses the string to pull the user name out.
    /// </summary>
    /// <param name="usernameDomain">The string to parse that must contain the username in either the domain\username or UPN format username@domain</param>
    /// <returns>The username or the string if no domain is found.</returns>
    public static string GetUsername(string usernameDomain)
    {
        if (string.IsNullOrEmpty(usernameDomain))
        {
            throw (new ArgumentException("Argument can't be null.", "usernameDomain"));
        }
        if (usernameDomain.Contains("\\"))
        {
            int index = usernameDomain.IndexOf("\\");
            return usernameDomain.Substring(index + 1);
        }
        else if (usernameDomain.Contains("@"))
        {
            int index = usernameDomain.IndexOf("@");
            return usernameDomain.Substring(0, index);
        }
        else
        {
            return usernameDomain;
        }
    }  

    protected void btnLogin_Click(object sender, EventArgs e)
    {
        string domainName = GetDomainName(txtUserName.Text); // Extract domain name form provide DomainUsername e.g Domainname\Username
        string userName = GetUsername(txtUserName.Text);  // Extract user name from provided DomainUsername e.g Domainname\Username
        IntPtr token = IntPtr.Zero;

        //userName, domainName and Password parameters are very obvious.
        //dwLogonType (3rd paramter): I used LOGON32_LOGON_INTERACTIVE, This logon type is intended for users who will be interactively using the computer, such as a user being logged on by a terminal server, remote shell, or similar process. This logon type has the additional expense of caching logon information for disconnected operations. For more details about this parameter please see http://msdn.microsoft.com/en-us/library/aa378184(VS.85).aspx
        //dwLogonProvider (4th parameter) : I used LOGON32_PROVIDER_DEFAUL, This provider use the standard logon provider for the system. The default security provider is negotiate, unless you pass NULL for the domain name and the user name is not in UPN format. In this case, the default provider is NTLM. For more details about this parameter please see http://msdn.microsoft.com/en-us/library/aa378184(VS.85).aspx
        //phToken (5th parameter): A pointer to a handle variable that receives a handle to a token that represents the specified user. We can use this handler for impersonation purpose. 
        bool result = LogonUser(userName, domainName, txtPassword.Text, 2, 0, ref token);
        if (result)
        {
            //If Sucessfully authenticated

            //When an unatuthenticated user try to visit any page of your application that is only allowed to view by authenticated users then,ASP.NET automatically redirect the user to login form and add ReturnUrl query string parameter that contain the url of a page that user want to visit, So that we can redirect the user to that page after authenticated. FormsAuthentication.RedirectFromLoginPage() method not only redirect the user to that page but also genrate an authentication token for that user.
            if (string.IsNullOrEmpty(Request.QueryString["ReturnUrl"]))
            {
                FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, false);
            }
            //If ReturnUrl query string parameter is not present , then we need to genrate authentication token and redirect the user to any page ( acording to your application need). FormsAuthentication.SetAuthCookie() method will genrate Authentication token 
            else
            {
                FormsAuthentication.SetAuthCookie(txtUserName.Text, false);
                Response.Redirect("default.aspx");


            }
        }
        else
        {
            //If not authenticated then display an error message
            Response.Write("Invalid username or password.");
        }
    }
}

</pre>

<h2>And We Are DONE!!!</h2>
<p>
We are done with authentication of windows account using form authentication.
</p>

<h2>Feedback</h2>
<p>You feedback will be very helpfull for me. You can send me an email at akhhttar @ gmail.com.  Thanks</p>
<!-------------------------------    That's it!   --------------------------->
</body>

</html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Common Public License Version 1.0 (CPL)

Share

About the Author

Muhammad Akhtar Shiekh
Software Developer Imanami Corporation
Pakistan Pakistan
I am Microsoft Certified Technology Specialist for Web Application Development. I have 4 year experience of Web and Distributed application development.I have considerable experience developing client / server software for major corporate clients using the Windows operating systems and .NET platform ( ASP.NET, C# , VB.NET).I have single and multi-threaded code development experience, as well as experience developing database and enterprise level distributed applications.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411028.1 | Last Updated 1 Jul 2009
Article Copyright 2009 by Muhammad Akhtar Shiekh
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid