Getting a session ID for the duration of the user's browing "session"

Hi - I m pretty sure this question has been asked before and for that I apologize but I cant find an answer.

I need a way to track a user’s session in the backend. Something that uniquely identifies this user for a duration of 30 minutes or so or while the user is browsing the website would suffice.

How can we achieve this and what are the implications of using this technique behind a load balancer without sticky sessions?

Thanks
Yannis

You could use the unique identifier in ServiceStack’s Temporary Session Cookie i.e. ss-id which lasts for the duration of the browsers session, or if you want to track a user across browser restarts you can use the ss-pid permanent cookie.

Otherwise you can set your own Cookie using your preferred name e.g. my-id

GlobalRequestFilters.Add((req, res, dto) =>
{
    var myId = req.GetItemOrCookie("my-id");
    if (myId == null)
    {
        var httpRes = res as IHttpResponse;
        if (httpRes != null)
        {
            myId = SessionExtensions.CreateRandomSessionId();
            httpRes.Cookies.AddSessionCookie("my-id", myId);
            req.SetItem("my-id", myId);
        }
    }
});

This will ensure that each HTTP Request from each user either has a Cookie or Request.Items[] named my-id which you can access using the IRequest.GetItemOrCookie() API.

Load balancers shouldn’t affect Cookies which just get passed through to the downstream HTTP Server.

1 Like

I m a bit confused. I see two JS requests from the browser to the server coming back with two successful responses where each response has a different ss-id and ss-pid. The ss-pid has an expiration time of now. Both are different between requests. The requests happen within 1 second from each other and without an extra page view in between.
I also tried setting a custom cookie like below and i dont see the cookie making it to the browser?

    public void Apply(IRequest req, IResponse res, Object dto)
    {
        var sessionId = req.GetItemOrCookie(COOKIE_NAME);
        if (sessionId == null) CreateNewSessionId(res);
    }

    private void CreateNewSessionId(IResponse res)
    {
        var httpRes = res as IHttpResponse;
        if (httpRes != null)
        {
            var cookie = new Cookie(COOKIE_NAME, Guid.NewGuid().ToString("N"))
            {
                Expires = DateTime.UtcNow.AddHours(_timeoutInHours)
            };
            httpRes.SetCookie(cookie);
        }
    }

and my AppConfigurator has

        app.Plugins.Add(new PostmanFeature());
        app.Plugins.Add(new ValidationFeature());
        app.PreRequestFilters.Add((httpReq, httpRes) => { httpReq.UseBufferedStream = true; });
        app.GlobalRequestFilters.Add(new CustomSessionFeature(configuration).Apply);

Thanks

Your implementation isn’t the same as mine, e.g. You’re not populating the req.Item so the request that creates the Cookie won’t return the sessionId when calling req.GetItemOrCookie().

Please provide the raw HTTP Request/Response Headers of the 2 JS requests from the same browser you’re referring to.

Hi - You use something called “SessionCookie”. The problem with this is that I couldnt set the expiration as I wanted. Therefore I resorted to normal .NET Cookies. This is to explain the difference in implementation. But it does return the value when I do GetItemOrCookie.

I ll post the browser requests in a second - let me take some screens

Here you go. I have intentionally removed Referrer, Host etc that add nothing to the question. As you see those are two requests happening one after the other.

The issue is that the Ajax Request isn’t sending Cookies which is why the Server is telling the client to add new Cookies in the HTTP Response.

How are you making the Ajax Request? If you’re using fetch() API you need to specify credentials: 'include' in order for the Cookies to be sent.

The ajax request is happening through a normal js lib not related to ServiceStack.

You need to make sure that the JS Requests are configured to send Cookies, currently they’re not sending Cookies. If they’re using the built-in fetch() API under the hood it needs to be configured with credentials:include in order to send it. Otherwise you need to find out how to configure the JS client to send it.