How to manage user concurrent connection if they logged out up-normally?

Dondon510 261 Reputation points
2022-05-11T10:42:41.79+00:00

I'm trying to maintain user list to manage user concurrent connection using ConcurrentDictionary

static ConcurrentDictionary<long, long> condict = new ConcurrentDictionary<long, long>();
internal static JObject Login(JObject _jo)
{

   if (!dictionary.ContainsKey(users_pid))
   {
       condict.TryAdd(users_pid, tenants_pid);
   }
   else
   {
       doMessage("Already logged in");
   }
 }

when user logout normally, I will use the following:

 string removedItem;
 bool result = condict.TryRemove(users_pid, out removedItem); 

Question:

How to control if the user logged out up-normally (ie. they just close their browser?)

need advice. thanks a lot

Developer technologies ASP.NET ASP.NET Core
0 comments No comments
{count} votes

5 answers

Sort by: Most helpful
  1. AgaveJoe 30,126 Reputation points
    2022-05-11T11:58:45.277+00:00

    There's no reliable way to detect the browser closed. The standard approach is to use a timeout. Rather than using a dictionary use a distributed cache or a table that tracks the last access DateTime.

    You did not method how your security works. But another method is to use a newest login wins. Each time the user logs in, set a GUID in a table and he same GUID in the user's token. On each request check if the GUID in the table matches the GUID in the token. The Identity framework has the Security Stamp column/property which can be reused for this requirement.

    0 comments No comments

  2. Dondon510 261 Reputation points
    2022-05-11T13:28:26.997+00:00

    @AgaveJoe

    thank you for your reply, I'm quite new with this, but I think I use a very simple authentication like below:

       services.Configure<CookiePolicyOptions>(options =>  
        {  
            options.CheckConsentNeeded = context => true;  
            options.MinimumSameSitePolicy = SameSiteMode.None;  
        });  
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();  
    

    in Home/Login Controller

    [HttpPost]
    [Route("/Home/Login")]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public JsonResult Login(string user_code, string password, string tenant_code)
    {
    ....
    var _cookie_options = new CookieOptions
    {
    Expires = DateTime.Now.AddDays(1),
    IsEssential = true
    };

                HttpContext.Response.Cookies.Append(Models.AppSettingsModel.Application.Cookie_Name, _jo_login_cookie.ToString(Newtonsoft.Json.Formatting.Indented), _cookie_options);  
                HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(_claims_identity));   
    

    and when Logging out

    [HttpGet]
    [Route("/Home/Logout")]
    public async Task<IActionResult> Logout()
    {
    if (HttpContext.Request.Cookies.Count > 0)
    {
    var siteCookies = HttpContext.Request.Cookies.Where(c => c.Key.Contains(Models.AppSettingsModel.Application.Cookie_Name) || c.Key.Contains("PTX-User_Info"));
    foreach (var cookie in siteCookies)
    {
    Response.Cookies.Delete(cookie.Key);
    }
    }

        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);  
        HttpContext.Session.Clear();  
        return RedirectToAction("Login");  
    }  
    

    and put [Authorize] when required in all controllers
    any suggestion?

    0 comments No comments

  3. AgaveJoe 30,126 Reputation points
    2022-05-11T14:35:50.85+00:00

    Web site operate over HTTP. The HTTP protocol is stateless. In order to make HTTP stateful data must be added to the HTTP request. You decided to use an authentication cookie to cache the user's identity.

    Session cookies, like the one you are using, expire when the browser is closed unless you specifically set the cookie to persist. You did not share the code that creates the cookie but you'll want to take a look at that code and make sure isPersistent is set to false.

    https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-6.0

    If you want to invalidate a cookie then then you need data in the cookie that matches data on the server. For example, lets say the cookie contains an Concurrency GUID of 3E5A33A6-AE73-4542-A7E0-657B6FDDC906 and the UserId is 1. If server has a matching GUID for UserId 1 then the authentication cookie is valid. Otherwise the cookie is invalid.

    0 comments No comments

  4. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2022-05-12T16:13:48.023+00:00

    your authentication cookie has a timeout. your connection dictionary also need a timeout that matches the cookie timeout (typically 20 minutes - but check your configuration).

    on every request update the connection dictionary with last access. at the same time loop thru the dictionary and delete items where the last access + timeout < now

    0 comments No comments

  5. Dondon510 261 Reputation points
    2022-05-13T01:34:24.32+00:00

    Thanks all,
    I did different way to manage user connection, I use websocket to handle this, I thought this more effective, since it would automatically detects if the user logged out by closing their browser.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.