In this article I will explain with an example, how to implement Role based Authorization and Authentication for user in ASP.Net using Forms Authentication.
 
 

Database

I have made use of the following table Users with the schema as follow.
Role based Authorization and Authentication in ASP.Net
 

Roles

Role based Authorization and Authentication in ASP.Net
 
The Roles table has two Roles i.e. Administrator and User
Role based Authorization and Authentication in ASP.Net
 
Note: You can download the database table SQL by clicking the download link below.
 
 

Login Page

This page will be used for allowing users login into the site.
I have used the same code and design as used in the article Simple User Login Form example in ASP.Net with little modifications for implementing roles.
 
 

HTML Markup

The HTML markup consists of an ASP.Net Login control for which the OnAuthenticate event handler has been specified.
<form id="form1" runat="server">
    <asp:Login ID="userLogin" runat="server" OnAuthenticate="ValidateUser"></asp:Login>
</form>
 
Role based Authorization and Authentication in ASP.Net
 
 

Namespaces

You will need to import the following namespaces.
C#
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Web.Security;
 
 
VB.Net
Imports System.Data
Imports System.Configuration
Imports System.Data.SqlClient
Imports System.Web.Security
 
 

Stored Procedure to Validate the User Credentials and get the Role

The following stored procedure is used to validate the user credentials and it also gets the assigned role, this stored procedure first checks whether the username and password are correct else returns -1.
If the username and password are correct but the user has not been activated, then the code returned is -2.
If the username and password are correct and the user account has been activated, then UserId and the Role is returned by the stored procedure.
CREATE PROCEDURE [dbo].[Validate_User]
       @Username NVARCHAR(20),
       @Password NVARCHAR(20)
AS
BEGIN
      SET NOCOUNT ON;
      DECLARE @UserId INT, @LastLoginDate DATETIME, @RoleId INT
     
      SELECT @UserId = UserId, @LastLoginDate = LastLoginDate, @RoleId = RoleId
      FROM Users WHERE Username @Username AND [Password] = @Password
     
      IF @UserId IS NOT NULL
      BEGIN
            IF NOT EXISTS(SELECT UserId FROM UserActivation WHERE UserId @UserId)
            BEGIN
                  UPDATE Users
                  SET LastLoginDate = GETDATE()
                  WHERE UserId = @UserId
                 
                  SELECT @UserId [UserId],
                              (SELECT RoleName FROM Roles
                               WHERE RoleId @RoleId) [Roles] -- User Valid
            END
            ELSE
            BEGIN
                  SELECT -2 [UserId], '' [Roles] -- User not activated.
            END
      END
      ELSE
      BEGIN
            SELECT -1 [UserId], '' [Roles] -- User invalid.
      END
END
 
 

Validating the User Credentials and determining the Role

The below event handler gets called when the Log In button is clicked. Here the Username and Password entered by the user is passed to the stored procedure and if the authentication is successful the UserId and the Role is returned.
The returned UserId and Role is used to create a FormsAuthentication ticket and the user is redirected either to the default page specified in the Web.Config or to the URL specified in the ReturnUrl QueryString parameter.
C#
protected void ValidateUser(object sender, EventArgs e)
{
    int userId = 0;
    string roles = string.Empty;
    string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
    using (SqlConnection  con = new SqlConnection(constr))
    {
        using (SqlCommand cmd = new SqlCommand("Validate_User"))
        {
            cmd.CommandType CommandType.StoredProcedure;
            cmd.Parameters.AddWithValue("@Username", userLogin.UserName);
            cmd.Parameters.AddWithValue("@Password", userLogin.Password);
            cmd.Connection = con;
            con.Open();
            SqlDataReader reader = cmd.ExecuteReader();
            reader.Read();
            userId = Convert.ToInt32(reader["UserId"]);
            roles = reader["Roles"].ToString();
            con.Close();
        }
        switch (userId)
        {
            case -1:
                userLogin.FailureText "Username and/or password is incorrect.";
                break;
            case -2:
                userLogin.FailureText "Account has not been activated.";
                break;
            default:
                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userLogin.UserName, DateTime.Now, DateTime.Now.AddMinutes(2880), userLogin.RememberMeSet, roles, FormsAuthentication.FormsCookiePath);
                string hash = FormsAuthentication.Encrypt(ticket);
                HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
 
                if (ticket.IsPersistent)
                {
                    cookie.Expires ticket.Expiration;
                }
                Response.Cookies.Add(cookie);
                Response.Redirect(FormsAuthentication.GetRedirectUrl(userLogin.UserName, userLogin.RememberMeSet));
                break;
        }
    }
}
 
VB.Net
Protected Sub ValidateUser(sender As Object, e As EventArgs)
    Dim userId As Integer = 0
    Dim roles As String = String.Empty
    Dim constr As String ConfigurationManager.ConnectionStrings("constr").ConnectionString
    Using con As New SqlConnection(constr)
        Using cmd As New SqlCommand("Validate_User")
            cmd.CommandType CommandType.StoredProcedure
            cmd.Parameters.AddWithValue("@Username", Login1.UserName)
            cmd.Parameters.AddWithValue("@Password", Login1.Password)
            cmd.Connection = con
            con.Open()
            Dim reader As SqlDataReader cmd.ExecuteReader()
            reader.Read()
            userId = Convert.ToInt32(reader("UserId"))
            roles = reader("Roles").ToString()
            con.Close()
        End Using
        Select Case userId
            Case -1
                 Login1.FailureText = "Username and/or password is incorrect."
                Exit Select
            Case -2
                 Login1.FailureText = "Account has not been activated."
                Exit Select
            Case Else
                Dim ticket As New FormsAuthenticationTicket(1, Login1.UserName, DateTime.Now, DateTime.Now.AddMinutes(2880), Login1.RememberMeSet, roles, _
                    FormsAuthentication.FormsCookiePath)
                Dim hash As String  FormsAuthentication.Encrypt(ticket)
                Dim cookie As New HttpCookie(FormsAuthentication.FormsCookieName, hash)
 
                If ticket.IsPersistent Then
                    cookie.Expires ticket.Expiration
                End If
                Response.Cookies.Add(cookie)
                Response.Redirect(FormsAuthentication.GetRedirectUrl(Login1.UserName, Login1.RememberMeSet))
                Exit Select
        End Select
    End Using
End Sub
 
Inside the Page_Load event of the Login page, the following code makes sure that if the user is already logged in then he will be logged out.
C#
protected void Page_Load(object sender, EventArgs e)
{
    if (!this.IsPostBack)
    {
        if (this.Page.User.Identity.IsAuthenticated)
        {
            FormsAuthentication.SignOut();
            Response.Redirect("~/Login.aspx");
        }
    }
}
 
VB.Net
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
    If Not Me.IsPostBack Then
        If Me.Page.User.Identity.IsAuthenticated Then
            FormsAuthentication.SignOut()
            Response.Redirect("~/Login.aspx")
        End If
    End If
End Sub
 
 

Global.asax file

Inside Application_AuthenticateRequest event of the Global.asax file, the Roles are fetched from the FormsAuthentication Ticket and assigned to the HttpContext User object. This way the Role is available throughout the Application through the Context.
C#
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    if (HttpContext.Current.User != null)
    {
        if (HttpContext.Current.User.Identity.IsAuthenticated)
        {
            if (HttpContext.Current.User.Identity is FormsIdentity)
            {
                FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
                FormsAuthenticationTicket  ticket = id.Ticket;
                string userData ticket.UserData;
                string[] roles = userData.Split(',');
                HttpContext.Current.User = new GenericPrincipal(id, roles);
            }
        }
    }
}
 
VB.Net
Sub Application_AuthenticateRequest(ByVal sender As ObjectByVal e As EventArgs)
    If HttpContext.Current.User IsNot Nothing Then
        If HttpContext.Current.User.Identity.IsAuthenticated Then
            If TypeOf HttpContext.Current.User.Identity Is FormsIdentity Then
                Dim id As FormsIdentity = DirectCast(HttpContext.Current.User.Identity, FormsIdentity)
                Dim ticket As FormsAuthenticationTicket id.Ticket
                Dim userData As String ticket.UserData
                Dim roles As String() = userData.Split(","c)
                HttpContext.Current.User = New GenericPrincipal(id, roles)
            End If
        End If
    End If
End Sub
 
 

Master Page

This master page is inherited by all pages and it is used to display the user greetings message, logout link and menu.
 
 

HTML Markup

The Master Page consists of an ASP.Net LoginView control, which consists of LoginName, LoginStatus and a Menu control populated using SiteMapDataSource.
Note: For more details about ASP.Net Menu control populated using SiteMapDataSource, please refer my article Using ASP.Net menu control.
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
    <style type="text/css">
        body { font-family: Arial; font-size: 10pt; }
        .main_menu { width: 100px; background-color: #fff; border: 1px solid #ccc !important; color: #000; text-align: center; height: 30px; line-height: 30px; margin-right: 5px; }
        .level_menu { width: 110px; background-color: #fff; color: #333; border: 1px solid #ccc !important; text-align: center; height: 30px; line-height: 30px; margin-top: 5px; }
        .selected { background-color: #9F9F9F; color: #fff; }
        input[type=text], input[type=password] { width: 200px; }
        table { border: 1px solid #ccc; }
        table th { background-color: #F7F7F7; color: #333; font-weight: bold; }
        table th, table td { padding: 5px; border-color: #ccc; }
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:LoginView ID="LoginView" runat="server">
                <LoggedInTemplate>
                    <div align="right">
                        Welcome
                    <asp:LoginName ID="LoginName1" runat="server" Font-Bold="true" />
                        <br />
                        <br />
                        <asp:Label ID="lblLastLoginDate" runat="server" />
                        <asp:LoginStatus ID="LoginStatus1" runat="server" />
                    </div>
                    <hr />
                    <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false"
                        SiteMapProvider="SiteMap" />
                    <asp:Menu ID="Menu" runat="server" DataSourceID="SiteMapDataSource1" Orientation="Horizontal"
                        OnMenuItemDataBound="OnMenuItemDataBound">
                        <LevelMenuItemStyles>
                            <asp:MenuItemStyle CssClass="main_menu" />
                            <asp:MenuItemStyle CssClass="level_menu" />
                        </LevelMenuItemStyles>
                    </asp:Menu>
                </LoggedInTemplate>
            </asp:LoginView>
            <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
            </asp:ContentPlaceHolder>
        </div>
    </form>
</body>
</html>
 
 

Sitemap and Website Structure

Below is the website structure where I have Login, Home and Contact pages in the root, these pages are accessible by both Administrator and User Roles.
Role based Authorization and Authentication in ASP.Net
 
While the Reports and Users pages are placed inside a folder named Admin which is accessible only by Administrator Role.
Below is the Web.sitemap file. For the pages that are accessible by both Administrator and User Roles, I have set roles="*" while for the pages that are accessible by Administrator Role, I have set roles="Administrator".
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/ AspNet/SiteMap-File-1.0" >
  <siteMapNode url="" title="Home" description="" roles ="*">
    <siteMapNode url="~/Home.aspx" title="Home" description="Home Page"  roles="*" />
    <siteMapNode url="javascript:;" title="Admin" description="Admin Page" roles ="Administrator">
      <siteMapNode url ="~/Admin/Users.aspx" title="Users" description="Users Page"></siteMapNode>
      <siteMapNode url ="~/Admin/Reports.aspx" title"Reports" description="Reports Page"></siteMapNode>
    </siteMapNode>
    <siteMapNode url="~/Contact.aspx" title="Contact" description="Contact Us Page" roles"*" />
  </siteMapNode>
</siteMap>
 
 

Web.Config Configuration

Root Web.Config file

The Root Web.Config file has following sections.
1. Connection String section
2. Authentication section - Here the Forms Authentication settings have been specified
3. Authorization section – Here I have allowed only authenticated users to access the pages by specifying .
4. Sitemap section – Here I have added a Sitemap provider for which securityTrimmingEnabled setting has been set to true. This is very necessary otherwise ASP.Net Menu control will not show/hide menu items as per Role.
<configuration>
    <connectionStrings>
        <add name="constr" connectionString="Data Source= .\SQL2019;Initial Catalog=LoginDB;user id=sa;password=pass@123;"/>
    </connectionStrings>
    <system.web>
        <compilation debug="true" targetFramework="4.8"/>
        <authentication mode="Forms">
            <forms defaultUrl="~/Home.aspx" loginUrl="~/Login.aspx" slidingExpiration="true" timeout="2880"/>
        </authentication>
        <authorization>
            <deny users="?"/>
        </authorization>
        <siteMap enabled="true" defaultProvider="SiteMap">
            <providers>
                <add name="SiteMap" type="System.Web.XmlSiteMapProvider" siteMapFile="~/Web.sitemap" securityTrimmingEnabled="true"/>
            </providers>
        </siteMap>
    </system.web>
</configuration>
 

Admin Folder Web.Config File

Inside the Admin Folder Web.Config file, we have simply restricted all users except users with Role Administrators.
<?xml version="1.0"?>
<configuration>
<system.web>
  <authorization>
    <allow roles="Administrator"/>
    <deny users="*"/>
  </authorization>
</system.web>
</configuration>
 
 

Screenshots

ASP.Net Menu when Administrator Logs in

Role based Authorization and Authentication in ASP.Net
 

ASP.Net Menu when normal User logs in

Role based Authorization and Authentication in ASP.Net
 
 

Downloads