Introduction

In many real-world applications such as banking portals, trading platforms, admin panels, and enterprise systems, it is common to restrict the number of concurrent logins per user.
Allowing unlimited logins using the same credentials can lead to security issues, license misuse, and data inconsistency.

This article explains a classic concurrent login / session-count control requirement, discusses the possible approaches, and provides a clean ASP.NET WebForms + SQL Server solution with working logic and output explanation.

Problem Statement

Requirements Summary

Possible Approaches

Option 1: ASP.NET Session Only (Not Recommended )

Not suitable for concurrent login control

Option 2: Database-Based Session Tracking (Recommended )

This is the correct and professional approach

Database Design

adminmaster Table

Stores user details and allowed session count.

CREATE TABLE adminmaster
(
    Srno INT PRIMARY KEY,
    userid VARCHAR(50),
    password VARCHAR(50),
    SessionCount INT DEFAULT 3
);

UserSessions Table

Tracks each login session.

CREATE TABLE UserSessions
(
    SessionId UNIQUEIDENTIFIER PRIMARY KEY,
    UserSrno INT NOT NULL,
    LoginTime DATETIME,
    LastActivity DATETIME,
    IsActive BIT,
    CONSTRAINT FK_UserSession_Admin
        FOREIGN KEY (UserSrno) REFERENCES adminmaster(Srno)
);

Concept Used

1. GUID-Based Session Identification

2. Least Recently Used (LRU) Strategy

3. Configurable Session Limit

Login Flow Logic

  1. Validate username & password

  2. Read allowed session count

  3. Fetch active sessions

  4. If session limit reached:

    • Kill the oldest active session

  5. Create a new session

  6. Allow login

ASP.NET WebForms Login Code

// Validate user
string sqlqry = @"
SELECT Srno, userid, SessionCount
FROM adminmaster (NOLOCK)
WHERE userid=@UserId AND password=@passwrd";

DataSet ds = SqlHelper.ExecuteDataset(con, CommandType.Text, sqlqry, param);

if (ds == null || ds.Tables[0].Rows.Count == 0)
{
    ErrLbl.Text = "Invalid UserID or Password";
    return;
}

// User is valid
DataRow row = ds.Tables[0].Rows[0];
int userSrno = Convert.ToInt32(row["Srno"]);
int maxSession = row["SessionCount"] == DBNull.Value ? 0 : Convert.ToInt32(row["SessionCount"]);

// Get active sessions
string activeQry = @"
SELECT SessionId
FROM UserSessions
WHERE UserSrno=@uid AND IsActive=1
ORDER BY LastActivity";

SqlParameter[] pActive =
{
    new SqlParameter("@uid", userSrno)
};

DataTable dtActive =
    SqlHelper.ExecuteDataset(con, CommandType.Text, activeQry, pActive)
    .Tables[0];

// Kill oldest session if limit reached
if (dtActive.Rows.Count >= maxSession)
{
    Guid oldSessionId =
        Guid.Parse(dtActive.Rows[0]["SessionId"].ToString());

    SqlParameter[] pKill =
    {
        new SqlParameter("@sid", oldSessionId)
    };

    SqlHelper.ExecuteNonQuery(
        con,
        CommandType.Text,
        "UPDATE UserSessions SET IsActive=0 WHERE SessionId=@sid",
        pKill);
}

// Create new session
Guid newSessionId = Guid.NewGuid();

SqlParameter[] pInsert =
{
    new SqlParameter("@sid", newSessionId),
    new SqlParameter("@uid", userSrno)
};

SqlHelper.ExecuteNonQuery(
    con,
    CommandType.Text,
    @"INSERT INTO UserSessions
      VALUES (@sid,@uid,GETDATE(),GETDATE(),1)",
    pInsert);

// Store session
Session["UserSrno"] = userSrno;
Session["SessionId"] = newSessionId;

Response.Redirect("Dashboard.aspx");

Session Activity Update (BasePage Concept)

protected void Page_Load(object sender, EventArgs e)
{
    if (Session["SessionId"] != null)
    {
        SqlParameter[] p =
        {
            new SqlParameter("@sid", Session["SessionId"])
        };

        SqlHelper.ExecuteNonQuery(
            con,
            CommandType.Text,
            @"UPDATE UserSessions
              SET LastActivity=GETDATE()
              WHERE SessionId=@sid AND IsActive=1",
            p);
    }
}

Auto-Expire Inactive Sessions (SQL Job)

UPDATE UserSessions
SET IsActive = 0
WHERE IsActive = 1
AND DATEDIFF(MINUTE, LastActivity, GETDATE()) > 30;

Purpose

Output Explanation

Scenario 1

User allowed 3 sessions, logs in 3 times
All logins allowed

Scenario 2

User logs in 4th time

Scenario 3

User closes browser without logout

Advantages of This Approach

Conclusion

Concurrent login control is a critical security feature in modern applications.
By using a database-driven session tracking mechanism with GUID-based session IDs and LRU session termination, we can efficiently control active logins without impacting user experience.

This solution is simple, clean, and production-ready for ASP.NET WebForms applications.