Start learning free

LESSON 83 OF 173 · BACKEND: USERS AND SECURITY

Who May Change Things?

Practice

Right now anyone can add a product to the shop: POST /products saves whatever it receives and never asks who is calling. A real shop lets everyone read its products, but only its owner may change them. The simplest way to tell the owner apart: the owner knows a secret, the admin key, and sends it with every request that changes something.

The key travels in a header: a name and a value that go with the request, next to the body. In C# the route's function takes HttpRequest request, and request.Headers["Name"].ToString() gives the header's value as text. When the request doesn't have that header, it gives an empty text, "". Here a made-up route picks its greeting from a header:

app.MapGet("/hello", (HttpRequest request) => {
    var lang = request.Headers["X-Language"].ToString();
    if (lang == "fr") {
        return Results.Json(new { message = "Bonjour" });
    }
    return Results.Json(new { message = "Hello" });
});

When the key is missing or wrong, the shop answers 401 Unauthorized, which means "I don't know who you are", and saves nothing. With the right key, the product is added as before. These are the requests your code must answer:

POST /products  {"name": "Vase", "price": 18}  (no key)                    →  401  {"error": "Missing or unknown key"}
POST /products  {"name": "Vase", "price": 18}  X-Admin-Key: let-me-in      →  401  {"error": "Missing or unknown key"}
POST /products  {"name": "Vase", "price": 18}  X-Admin-Key: admin-key-123  →  201  {"id": 9, "name": "Vase", "price": 18}
GET /products/9   →  200  {"category": null, "id": 9, "name": "Vase", "price": 18, "stock": 0}
GET /products/10  →  404  {"error": "Product not found"}

Your task: store the secret "admin-key-123" in a constant string ADMIN_KEY. As the first line of the MapPost route's function, read the X-Admin-Key header into key, and when it isn't the admin key, return {"error": "Missing or unknown key"} with the status 401 before anything is saved.


Assignment
Follow the Coding Tutorial to protect POST /products with the admin key.


Hint
Put the check before data.GetProperty and the INSERT: once the row is saved, a 401 comes too late. One != covers both cases, because a missing header gives "", and "" isn't the key either.


STEP 1 OF 4
    Ctrl + Enter to check