Display Session timeout warning message before Session expires in ASP.NET Core


I can able to set the session end the below code.

services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(2); });

I need to extend the session after 20 minutes and if show the session time out warning message to the user and so the user can extend their time out from the application UI.


Answers:


You already have session timeout code in your question. By the way, default value is 20 minutes. If you want more information, you can read more at Configuring Session.

As far as, I know ASP.NET doesn't have a build-in mechanism to display session expire notification message. So, we have to write our own.

Here is mine, and here is the usage. You are feel free to use it. Since I use Kendo UI, I use Kendo UI Window for the dialog. You could replace it with jQuery UI, if you do not want to use Kendo UI.

enter image description here

_SessionExpireNotification.cshtml

I keep the setting inside appsettings.json. You could hard coded them in this file.

@using Asp.Core
@using Microsoft.Extensions.Options
@using Asp.Web.Common

@inject IUserSession UserSession
@inject IOptions<AppSettings> AppSettings

@if (UserSession.IsAuthenticated)
{
    @(Html.Kendo().Window()
          .Name("SessionExpireNotification")
          .Title("Need More Time?")
          .Modal(true)
          .Content(@<text>
            <p>
                Your session is about to expire. You will be automatically signed out in
            </p>
            <h2 style="margin-top: 0">
                <span id="logout-counter-span">[email protected](AppSettings.Value.CookieAuthentication.SessionExpireNotificationMinutes):00</span>
            </h2>
            <p>
                To continue your session, select <strong>Stay Signed In</strong>.
            </p>
            <p>
                <button id="stay-logged-in-button" type="button" class="btn btn-primary">
                    Stay Signed In
                </button>
                <button id="signout-button" type="button" class="btn btn-default">
                    Sign out
                </button>
            </p>
        </text>)
          .Width(450)
          .Visible(false)
          .Events(ev => ev.Close("onSessionExpireNotificationClose"))
    )

    <script>

        var notificationInterval,
            logoutInterval,
            logoutCounterSpan;

        function startNotificationCounter() {
            var counter = @AppSettings.Value.CookieAuthentication.ExpireMinutes;
            notificationInterval = setInterval(function() {
                    counter--;
                    if (counter === @AppSettings.Value.CookieAuthentication.SessionExpireNotificationMinutes) {
                        $("#SessionExpireNotification").data("kendoWindow").center().open();
                        startLogoutCounter();
                    }
                },
                60000);
        }

        function startLogoutCounter() {
            var counter = @(AppSettings.Value.CookieAuthentication.SessionExpireNotificationMinutes*60);
            logoutInterval = setInterval(function() {
                    counter--;
                    if (counter < 0) {
                        $("#logoutForm").submit();
                    } else {
                        var m = Math.floor(counter / 60);
                        var s = Math.floor(counter % 60);
                        var mDisplay = m < 10 ? "0" + m : m;
                        var sDisplay = s < 10 ? "0" + s : s;
                        logoutCounterSpan.text(mDisplay + ":" + sDisplay);
                    }
                },
                1000);
        }

        function resetCounters() {
            clearInterval(notificationInterval);
            clearInterval(logoutInterval);
            logoutCounterSpan.text("[email protected](AppSettings.Value.CookieAuthentication.SessionExpireNotificationMinutes):00");
            startNotificationCounter();
        }

        function onSessionExpireNotificationClose() {
            resetCounters();
        }

        $(function() {
            logoutCounterSpan = $("#logout-counter-span");

            startNotificationCounter();

            $("#stay-logged-in-button").click(function() {
                $.get("@Url.Action("Index", "KeepAlive", new {area = ""})",
                    null,
                    function(data) {
                        resetCounters();
                        $("#SessionExpireNotification").data("kendoWindow").center().close();
                    }
                );
            });

            $("#signout-button").click(function() {
                $("#logoutForm").submit();
            });
        });

    </script>
}

Extending the session timeout is easy. You just call a dummy action method.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Asp.Web.Controllers
{
    [AllowAnonymous]
    public class KeepAliveController : Controller
    {
        //
        // GET: /KeepAlive
        [AllowAnonymous]
        public ActionResult Index()
        {
            return Content("I am alive!");
        }
    }
}