Sprint 2: Authentication (Weeks 5–6)
Right now anyone can post or delete a job. Sprint 2 adds user accounts so that only registered, logged-in users can post jobs, and only admins can delete them. This is the sprint that introduces the most cross-cutting change to the codebase — coordinate with your teammates before you start.
Sprint goal
Users can register, log in, and log out. Job creation is protected behind a login wall. Passwords are hashed. Sessions are stored in signed cookies.
Design decisions (Tech Lead owns these)
Before backend engineers write a line of auth code, the Tech Lead must open an issue that answers:
- What library handles password hashing? (
passlib[bcrypt]) - What does the
CurrentUserdependency look like? (type, file location) - Where does the session token live? (signed cookie via
itsdangerous) - What happens when an unauthenticated user hits a protected route? (redirect to
/login)
Engineers should not start auth work until this issue is closed and merged into a docs/auth-design.md file.
What each role ships this sprint
Backend
- Add
Usermodel toapp/models/user.py(id, email, hashed_password, is_admin) - Add
POST /registerandPOST /loginroutes inapp/routes/auth.py - Add
POST /logoutroute - Create a
CurrentUserFastAPI dependency inapp/dependencies.py - Protect
POST /jobsandDELETE /jobs/{id}with theCurrentUserdependency
Add these packages:
bash
uv add passlib[bcrypt] itsdangerousFrontend
- Create
templates/auth/login.htmlandtemplates/auth/register.html - Update
templates/base.htmlnavbar to show Login/Register or username + Logout - Show an error message on failed login (
Invalid email or password) - Redirect to
/jobsafter successful login
QA
Write tests for every auth path:
POST /register — success
POST /register — duplicate email
POST /login — success, session cookie set
POST /login — wrong password
POST /logout — clears session
POST /jobs — authenticated user can post
POST /jobs — unauthenticated user gets 302 to /loginDevOps
- Add
SECRET_KEYenvironment variable to the Render deployment - Document how to rotate the secret key without invalidating all sessions
- Add
SECRET_KEYto.github/workflows/ci.ymlas a test secret (use a dummy value)
Tech Lead
- Write
docs/auth-design.mdbefore sprint work begins (see above) - Review all auth PRs for security issues: no plaintext passwords, no SQL injection, cookies are
HttpOnly - Ensure the
CurrentUserdependency is used consistently — reject PRs that inline auth logic
PM
- Break the sprint goal into granular issues (User model, routes, templates, tests are separate issues)
- Track blockers: backend auth must merge before frontend can wire up the navbar
Security notes for reviewers
When reviewing auth PRs, check for:
- [ ] Passwords stored as bcrypt hashes, never plaintext
- [ ] Session cookie has
HttpOnly=TrueandSameSite="lax" - [ ] Login form does not reveal whether the email exists ("Invalid email or password", not "No account with that email")
- [ ]
SECRET_KEYis read from an environment variable, never hard-coded
References
- passlib bcrypt docs
- FastAPI security tutorial
- itsdangerous signed cookies
- OWASP authentication cheat sheet
Sprint 2 checklist
- [ ]
docs/auth-design.mdis merged before sprint coding starts - [ ] Register and login work end-to-end on the deployed site
- [ ] All auth routes have tests
- [ ] Passwords are bcrypt-hashed (verify with a reviewer)
- [ ]
SECRET_KEYis in an env var, not in code - [ ] You have 2+ merged PRs
- [ ] You have given 2+ reviews