Fetching session state without sending HTTP request from front end

1.6k views Asked by At

Setup ASP.NET Core with Reactjs + Redux + Saga. It needs to notify the user when asp.net core session is expired. But the problem is by sending GET requests to check the session status we extend the session which means the session will not ever be over unless the tab in the browser will be closed(then GET requests won't be sent). This is the session setup Startup.cs

services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromSeconds(60 * 60);
                options.Cookie.HttpOnly = true;
            });

And then we send every 5 minute request from client to get identity:

function* checkSessionIsValid() {
    try {
        const response = yield call(axios.get, 'api/Customer/FetchIdentity');

            if (!response.data) {
                return yield put({
                    type: types.SESSION_EXPIRED,
                });

            yield delay(300000);
            return yield put({ type: types.CHECK_SESSION_IS_VALID });
        }
        return;
    } catch (error) {
        return;
    }
}

And the backend endpoint(_context is IHttpContextAccessor):

        [HttpGet("FetchIdentity")]
        public LoginInfo GetIdentity()
        {
            if (SessionExtension.GetString(_context.Session, "_emailLogin") != null)
            {
                return new LoginInfo()
                {
                    LoggedInWith = "email",
                    LoggedIn = true,
                    Identity = ""
                };
            }

            return null;
        }

So we get session info from SessionExtension. But probably there is some way of getting it without connecting to the back end?

2

There are 2 answers

1
Chris Pratt On

What you're asking isn't possible, and frankly doesn't make sense when you understand how sessions work. A session only exists in the context of a request. HTTP is a stateless protocol. Sessions essentially fake state by having the server and client pass around a "session id". When a server wants to establish a "session" with a client, it issues a session id to the client, usually via the Set-Cookie response header. The client then, will pass back this id on each subsequent request, usually via the Cookie request header. When the server receives this id, it looks up the corresponding session from the store, and then has access to whatever state was previously in play.

The point is that without a request first, the server doesn't know or care about what's going on with a particular session. The expiration part happens when the server next tries to look up the session. If it's been too long (the session expiration has passed), then it destroys the previous session and creates a new one. It doesn't actively monitor sessions to do anything at a particular time. And, since as you noted, sessions are sliding, each request within the expiration timeframe resets that timeframe. As a result, a session never expires as long as the client is actively using it.

Long and short, the only way to know the state of the session is to make a request with a session id, in order to prompt the server to attempt to restore that session. The best you can do if you want to track session expiration client-side is to set a timer client-side based on the known timeout. You then need to reset said time, with every further request.

 var sessionTimeout = setTimeout(doSomething, 20 * 60 * 1000); // 20 minutes

Then, in your AJAX callbacks:

 clearTimeout(sessionTimeout);
 sessionTimeout = setTimeout(doSomething, 20 * 60 * 1000);
0
Petter Pettersson On

Perhaps the SessionState attribute can be utilized.

[SessionState(SessionStateBehavior.Disabled)]

https://msdn.microsoft.com/en-US/library/system.web.mvc.sessionstateattribute.aspx?cs-save-lang=1&cs-lang=cpp

EDIT: Realized that you're using .NET Core, not sure if the SessionState attribute or anything similar exist as of today.