Start learning free

LESSON 92 OF 173 · BACKEND: USERS AND SECURITY

Sessions with Cookies in C#

Practice

A cookie is a small piece of data a site gives the browser with an answer. The browser keeps it and sends it back, on its own, with every later request to that site. That's how a website stays logged in without adding an Authorization header to each request.

ASP.NET Core's session works through such a cookie. The cookie carries only a protected session id; the values stay on the server, in the memory cache that AddDistributedMemoryCache() adds. You turn sessions on with builder.Services.AddSession() and app.UseSession(). Then SetString keeps text under a key, and GetString reads it back, or gives null when the key isn't there. For example, two routes could remember a shopper's favorite color:

app.MapPost("/color", (JsonElement data, HttpContext context) => {
    context.Session.SetString("color", data.GetProperty("color").GetString());
    return Results.Json(new { color = context.Session.GetString("color") });
});

app.MapGet("/color", (HttpContext context) => {
    return Results.Json(new { color = context.Session.GetString("color") ?? "blue" });
});

In this lesson, /login also keeps the token in the session, and CurrentUser uses it when a request brings no Authorization header. When the header is there, it still wins. The tests use one client that keeps its cookies, like a browser:

GET /me  (no header, no cookie yet)  →  401  {"error": "Login required"}
POST /login  {"email": "ana@example.com", "password": "secret123"}  →  200  {"token": "…"}
GET /me  (no header)  →  200  {"email": "ana@example.com", "id": 2, "role": "customer"}
GET /welcome  (no header)  →  200  Welcome back, ana@example.com!
POST /products  {"name": "Desk", "price": 120}  (no header)  →  403  {"error": "Admins only"}
POST /login  {"email": "admin@example.com", "password": "admin-pass-123"}  →  200  {"token": "…"}
POST /products  {"name": "Desk", "price": 120}  (no header)  →  201  {"id": 9, "name": "Desk", "price": 120}
GET /me  (Bearer Ana's token)  →  200  {"email": "ana@example.com", "id": 2, "role": "customer"}
GET /me  (no header)  →  200  {"email": "admin@example.com", "id": 1, "role": "admin"}

Your task: the memory cache and the HttpContext context parameter of /login are already there. Turn sessions on with builder.Services.AddSession() and app.UseSession(), keep the token with context.Session.SetString("token", token) at login, and let CurrentUser take the token from the session when the header gives none.


Assignment
Follow the Coding Tutorial to keep users logged in with a session cookie.


Hint
Without the header, header.Replace("Bearer ", "") gives the empty text "": that's when to read request.HttpContext.Session.GetString("token"). It gives null for a client with no token in its session yet, so add ?? "".


STEP 1 OF 5
    Ctrl + Enter to check

    Auth Sessions in C#

    Keep going with C#1,600+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free