Start learning free

LESSON 7 OF 20 · SECURITY: TOKENS AND SESSIONS

Signed Tokens: Check the Signature in Python

Practice

After login, the shop gives you a token made of two parts joined by a dot: payload.signature. The payload is your JSON, like {"email": "ana@example.com", "role": "customer"}, in base64. The signature is HMAC-SHA256 of the payload with the server's SECRET; the given sign(payload) makes it.

The attack: base64 is not a lock, anyone can decode it. A visitor writes "role": "admin" into the payload, encodes it again and glues any signature after the dot. The starting code's read_token reads the payload and never looks at the signature, so the attacker gets every customer's name and email from /admin/customers.

Only the server knows SECRET, so only the server can make the right signature for a payload. To check a token, sign its payload again and compare the result with the signature that came with it. Compare with hmac.compare_digest, which takes the same time however many letters match:

hmac.compare_digest("abc123", "abc123")    # True
hmac.compare_digest("abc123", "abc999")    # False

The forged token below says "role": "admin" with a made-up signature. The routes must answer:

POST /login  (Ana's password)          →  200  {"token": "…"}
GET /me  (Ana's token)                 →  200  {"email": "ana@example.com", "role": "customer"}
GET /admin/customers  (Ana's token)    →  403  {"error": "Admins only"}
GET /me  (forged token)                →  401  {"error": "Login required"}
GET /admin/customers  (forged token)   →  401  {"error": "Login required"}
GET /me  (no token)                    →  401  {"error": "Login required"}
POST /login  (the admin's password)    →  200  {"token": "…"}
GET /admin/customers  (admin's token)  →  200  [{"email": "ana@example.com", "id": 1, "name": "Ana Pop"}, …]

Your task: in read_token, below the split line, set expected to sign(payload). When signature and expected aren't equal by hmac.compare_digest, return None, so the routes answer 401.


Assignment
Follow the Coding Tutorial to make read_token check the signature before it trusts the payload.


Hint
read_token already returns None for a token without exactly one dot, and the routes turn None into 401. A wrong signature takes the same way out.


STEP 1 OF 3
    Ctrl + Enter to check

    Secx Jwt Verify in Python

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