Start learning free

LESSON 88 OF 173 · BACKEND: USERS AND SECURITY

Tokens in Go

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 its bytes come from crypto/rand (never math/rand, whose numbers can be predicted): rand.Read fills a slice of 16 bytes with random values, and hex.EncodeToString writes them as 32 hexadecimal characters, a new value every time. 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:

codeBytes := make([]byte, 4)
rand.Read(codeBytes)
code := hex.EncodeToString(codeBytes)   // 8 random characters, like "9f1c02ab"
db.Exec("INSERT INTO coupons (code, percent) VALUES (?, ?)", 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 POST /login handler, after the 401 check, make 16 random bytes with rand.Read, turn them into the hex text token, store it with the user's id, and answer {"token": token}.


Assignment
Follow the Coding Tutorial to create the tokens table and make the POST /login handler 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 id from the row for user_id. db.Exec saves the row right away; there is no commit to write.


STEP 1 OF 6
    Ctrl + Enter to check

    Auth Tokens in Go

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