Start learning free

LESSON 88 OF 173 · BACKEND: USERS AND SECURITY

Tokens

Practice

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 Node's crypto module: crypto.randomBytes(16).toString("hex") gives 16 random bytes written as 32 hexadecimal characters, a new string 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:

const code: string = crypto.randomBytes(4).toString("hex");   // 8 random characters, like "9f1c02ab"
db.prepare("INSERT INTO coupons (code, percent) VALUES (?, ?)").run(code, 10);

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 the /login route, after the 401 check, make a token with crypto.randomBytes(16).toString("hex"), store it with the user's id, and answer { token: token }.


Assignment
Follow the Coding Tutorial to create the tokens table and make the /login route 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 end the route with res.json: a route that sends no answer leaves the client waiting.


STEP 1 OF 4
    Ctrl + Enter to check