ASP.NET Session Cookie not Being Set

Issue with ASP.NET Core Session Cookies Not Being Set (Intermittent)

I’m using ASP.NET Core sessions, and for some reason, the middleware is not consistently sending the Set-Cookie header for the .AspNetCore.Session cookie. This issue becomes even stranger because sometimes, it works just fine, but other times, it doesn’t.

For example, on DevMachine1, it doesn’t work currently, but if I go to DevMachine2 and run the exact same repo with the same middleware configuration, it works as expected.

Problem Context:

Program.cs:

builder.Services.AddHttpClient();
builder.Services.AddHttpContextAccessor();
builder.Services.AddControllersWithViews();
builder.Services.AddScoped<AutomateAPIService>();
builder.Services.AddScoped<AutomateDataService>();
// builder.Services.AddSingleton<PersistService>(); // For Future Persist Integration, removing to test sessions.
builder.Services.AddScoped<AutomateLoginService>();
builder.Services.AddTransient<JsonParserService>();
builder.Services.AddSingleton<IMongoClient, MongoClient>(sp => new MongoClient(connectionUri));
builder.Services.AddTransient<PersistService>();
builder.Services.AddTransient<SessionValidationService>();
builder.Services.AddScoped<SessionAuthorizationFilter>();
builder.Services.AddScoped<DeviceJsonParser>();
builder.Services.AddDistributedMemoryCache();

// MongoSessionStorage
builder.Services.AddSingleton(sp =>
{
    var client = sp.GetRequiredService<IMongoClient>();
    var database = client.GetDatabase("SessionDatabase");
    return database.GetCollection<BsonDocument>("Sessions");
});

// Add Session
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(60);
    options.Cookie.SecurePolicy = CookieSecurePolicy.None;
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
    options.Cookie.SameSite = SameSiteMode.Lax;
});

builder.Services.AddSingleton<ISessionStore, MongoDbSessionStore>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseSession();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

As you may notice, sessions are being stored in a MongoDB database. This setup has worked before and, on some machines, still works intermittently. Rolling back to the In-Memory cache did not resolve the issue either.

Logs:

We log out of the session store and see the following:

Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
      Failed to determine the https port for redirect.
info: WebAppApiTest.Services.MongoDbSessionStore[0]
      Setting SessionKey, System.Byte[] for session
info: WebAppApiTest.Controllers.HomeController[0]
      SessionKey value: SessionValue
info: WebAppApiTest.Services.MongoDbSessionStore[0]
      Attempting to commit session ca2084a4-23c1-f13f-4bb2-661251e14d38
info: WebAppApiTest.Services.MongoDbSessionStore[0]
      Session ca2084a4-23c1-f13f-4bb2-661251e14d38 committed successfully. Matched: 0, modified 0, Upserted: True

We can see session IDs, so we know the middleware is working to a degree, but no session cookie is being set, meaning our session store never has the correct or persistent session ID to refer to.

Controller Test for Forcing Session Interaction:

I tried forcing session interaction at my LoginController to see if I could get ASP.NET to send the session cookie:

public IActionResult AutomateLogin()
{
    HttpContext.Session.SetString("SessionKey", "SessionValue"); 
    var sessionValue = HttpContext.Session.GetString("SessionKey");
    _logger.LogInformation($"SessionKey value: {sessionValue}");
    return View(new AutomateLoginModel());
}

Logs confirm that session interaction is happening:

info: WebAppApiTest.Services.MongoDbSessionStore[0]
      Setting SessionKey, System.Byte[] for session
info: WebAppApiTest.Controllers.AutomateLoginController[0]
      SessionKey value: SessionValue
info: WebAppApiTest.Services.MongoDbSessionStore[0]
      Attempting to commit session 6207e6cb-6eeb-688e-0e37-c60e32f4a004
info: WebAppApiTest.Services.MongoDbSessionStore[0]
      Session 6207e6cb-6eeb-688e-0e37-c60e32f4a004 committed successfully. Matched: 0, modified 0, Upserted: True

Still, no session cookie is being set.

Summary of Issue:

  • The session cookie is not being set intermittently, across different machines and at different times.
  • Session IDs are being generated and committed to the store (MongoDB or In-Memory, the issue persists).
  • The middleware configuration is identical across working and non-working environments.
  • I expect the session cookie to be set with each new session.

My Question:

What could cause ASP.NET Core sessions to fail intermittently when setting the session cookie (.AspNetCore.Session)? Why would the session cookie be set on some machines but not on others, even with identical configurations?

I did verify this across several browsers and confirmed that the Set-Cookie header is not present. I did find out why:

So in the SessionMiddleware class we evaluate whether or not we should include the header here:

IMPORTANT UPDATE:

In SessionMiddleware.cs (An ASP.NET native class)

The Set-Cookie header is conditionally evaluated on whether or not the response is started. If the response is already started we can no longer use the Set-Cookie header.

However, after running through the debug for awhile, it looks like even though my response HasStarted value = false we do not set _shouldEstablishSession = true.

SessionMiddleware.cs

    internal bool TryEstablishSession()
    {
        return (_shouldEstablishSession |= !_context.Response.HasStarted);
    }

And when I set a break point at the return line it is not being hit at all, so even though my Response.HasStarted is false and therefore _shouldestablishSession should be true

    private static Task OnStartingCallback(object state)
    {
        var establisher = (SessionEstablisher)state;
        if (establisher._shouldEstablishSession)
        {
            establisher.SetCookie();
        }
        return Task.CompletedTask;
    }

And therefore executing in this task, we have a false value for _shouldEstablishSession.

Not sure why it’s not evaluating, but this is for sure the issue for why the Set-Cookie header is not being included. Could be a middleware pipeline issue but not sure why it’s manifesting as an intermittent issue.

6

After reviewing the underlying class responsible for creating and sending session cookies in ASP.NET Core, I realized that the method TryEstablishSession was not being invoked. This method is crucial for setting session cookies and should be passed as a delegate when creating a session.

Here’s how the Create method in the custom session store should look:

public ISession Create(string sessionKey, TimeSpan idleTimeout, TimeSpan ioTimeout, Func<bool> tryEstablishSession, bool isNewSession)
{
    return new MongoDbSession(sessionKey, _sessionCollection, idleTimeout, _logger, tryEstablishSession);
}

Once the tryEstablishSession delegate was passed to session operations like LoadAsync and CommitAsync, the session cookie started being set properly. The breakpoint in the SessionMiddleware class was finally being hit, and the session cookie was included in the response.

The Fix:

The tryEstablishSession delegate should be passed when creating a session and used throughout the session lifecycle. This ensures that the underlying middleware can invoke it, allowing session cookies to be set.

While the issue appeared intermittent at first, this solution fixed the problem, and the session cookie is now consistently set.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật