pip install djangorestframework-simplejwt. Do not look at solutions.md before submitting.
Exercise 1 — Token login
- Configure SimpleJWT (access 10 min, refresh 7 days, rotation + blacklist) and the token endpoints. Log in with your test user and note both tokens.
- Call
GET /api/reservations/withAuthorization: Bearer <access>: 200. Without the header: 401. With an expired token (wait, or set the lifetime to 5s): 401 withtoken_not_valid. - Refresh: get a new access and verify the old refresh no longer works (blacklist after rotation).
Exercise 2 — Look inside the JWT
- Paste your access token into jwt.io (or
base64 -deach part): which claims do you see? Is your email there? Could your card number go there? - Change one character of the payload and use the token: what exact error? (invalid signature).
- Question: what would happen if the payload carried the role and someone edited it? (without the signature they can't — explain the mechanism).
Exercise 3 — Where the token lives
- Serve a mini test page that fetches your API with the access token in localStorage vs in an
HttpOnly; SameSite=Laxcookie. Inject a simulated "XSS" (ascriptreading storage/document.cookie): what can it steal in each case? - Configure
CSRF_TRUSTED_ORIGINSand test the cookie + SameSite=Lax flow from an "evil origin" (curl with a fake Origin): does it pass Django's CSRF? - Write the 3-line summary for your README: what token lives where on TicketFlow and why.
Exercise 4 — ADR-0008
Write the ADR "Authentication: short JWT + rotated refresh in an HttpOnly cookie" — context (web + mobile, revocable purchases), decision, rejected alternatives (session only, long JWT in localStorage), consequences (blacklist in Redis/DB, logout = refresh blacklist, mobile with keychain).
Exercise 5 — Logout that actually works
- Implement an authenticated
POST /api/auth/logout/: blacklist the user's refresh. Verify: after logout, the refresh no longer yields an access. - And the already-issued access (valid up to 10 min)? Is that acceptable? How would you cut it otherwise (hint: blacklist by jti checked on every request — and what do you pay)?
Submit
Paste configuration, tokens (trimmed: NOT the real ones!) and conclusions. Next: Lesson 19 — OAuth2 and OpenID Connect.