HTTP has no memory: every request arrives on its own. After Ana logs in, the next request from Ana's browser carries nothing that says who is asking. The browser could send the password every time, but then the password would travel again and again. Instead, a successful login hands out a token: a random ticket that stands for the user.
The token must be impossible to guess, so it comes from Python's secrets module: secrets.token_hex(16) gives 16 random bytes written as 32 hexadecimal characters, a new value on every call. The shop keeps each token in a tokens table next to its user's id, so it can later look up whose ticket it is. The same idea for a coupon code:
code = secrets.token_hex(4) # 8 random characters, like '9f1c02ab'
db.execute("INSERT INTO coupons (code, percent) VALUES (?, ?)", (code, 10))
db.commit()
The client keeps the token and sends it with each later request, in the header Authorization: Bearer <token> ("bearer": whoever holds the ticket). Reading that header is the next lesson.
The tests first sign up Ana (id 1) and Ben (id 2). <token> stands for a random value that changes on every run, and GET /check/tokens is the grader's look into your table:
POST /login {"email": "ana@example.com", "password": "secret123"} → 200 {"token": "<token>"}
POST /login {"email": "ben@example.com", "password": "tea4two"} → 200 {"token": "<token2>"}
POST /login {"email": "ana@example.com", "password": "secret123"} → 200 {"token": "<token3>"}
POST /login {"email": "ana@example.com", "password": "secret999"} → 401 {"error": "Wrong email or password"}
GET /check/tokens → 200 [{"token": "<token>", "user_id": 1},
{"token": "<token2>", "user_id": 2},
{"token": "<token3>", "user_id": 1}]
Your task: create a tokens table with the columns token and user_id. In login, after the 401 check, make a token with secrets.token_hex(16), store it with the user's id, and answer {"token": token}.
Assignment
Follow the Coding Tutorial to create the tokens table and make login hand out a new token on every successful login.
Hint
Every login adds a new row, even for the same user: Ana logs in twice, so Ana gets two tokens. Use user["id"] for user_id, and don't forget db.commit() after the INSERT.
Free plan: 30 tutor messages. PRO is unlimited.
