In this assignment, you will extend the Snippets API to support multiple authentication mechanisms and reflect on their trade-offs.
You will:
- Solidify the secure password and login flow you implemented in class.
- Add database-stored tokens on top of the existing login logic.
- Deepen either your JWT or session-based authentication (or both, if you have time).
- Add a simple API-key-protected machine-style endpoint.
- Go to/create a
node/week3directory in yourhyf-assignmentrepo. - Copy or link your existing Snippets API code from week 2, so that you have:
- A working database connection and Knex setup.
- Existing snippets-related endpoints under
/api/snippets.
- Make sure your database contains the required tables for the Snippets API and that you can run it locally without errors.
- Ensure you have environment variables (or config values) for:
JWT_SECRETSESSION_SECRETAPI_KEY(for the machine-style endpoint).
If you are missing any of these pieces, revisit the week 3 session materials and implement the in-class steps first before moving on.
Start from the state of your Snippets API at the end of the week 3 session.
Your goals:
- Make sure the secure
/loginendpoint using bcrypt is correctly implemented. - Make sure at least one auth mechanism (JWT or sessions) from the session is working reliably.
- Verify that:
userstable exists and contains at least one user with a hashed password./login:- Looks up the user by email.
- Uses
bcrypt.compareto check the password. - Returns appropriate HTTP status codes on success (
200) and failure (401).
- If using JWT:
- The login route issues a JWT signed with
JWT_SECRET. - A middleware verifies the token and attaches user info to
req.user.
- The login route issues a JWT signed with
- If using sessions:
- Session middleware is configured with
SESSION_SECRET. - Login sets
req.session.userId. - A middleware checks for
req.session.userIdand rejects unauthenticated requests.
- Session middleware is configured with
- Add or update error handling so that:
- You do not leak sensitive details in responses.
- You log enough server-side information to debug issues.
Document briefly (e.g. in comments or a short AUTH_NOTES.md) which auth mechanism you have working at this stage.
Next, add database-stored tokens to your Snippets API, in addition to your existing mechanism.
- Create a
tokenstable with at least:id(primary key)user_id(foreign key tousers.id)token(unique string)created_at(timestamp)expires_at(timestamp, optional)
- Implement a
/login-tokenroute that:- Reuses your secure username/password check.
- Generates a random token (for example using
crypto.randomBytes). - Stores the token and user ID in the
tokenstable. - Returns the token to the client in JSON.
- Implement
authTokenmiddleware that:- Reads the
Authorizationheader (Bearer <token>). - Looks up the token in the
tokenstable. - (Optionally) checks
expires_at. - Attaches the user to
req.useror returns401on failure.
- Reads the
- Protect at least two existing Snippets API endpoints using
authToken, for example:POST /api/snippetsDELETE /api/snippets/:id
- Implement a
/logout-tokenroute that:- Deletes or invalidates the token record from the
tokenstable.
- Deletes or invalidates the token record from the
Read thoroughly the following article on implementing authorisation using JWT and Express or find other resources online.
Extend your implementation by:
- Improving error handling (e.g. distinguish between missing, invalid, and expired tokens in a safe way).
- Adding role-based checks in middleware:
- all users can see snippets
- all logged in users can post snippets
- some logged in users can delete snippets
- Clearly document (in code comments or
AUTH_NOTES.md) how to:- Obtain credentials and log in.
- Use the improved mechanism (which headers/cookies are expected).
- Log out or otherwise invalidate access.
Finally, add a simple API-key-protected endpoint intended for machine-to-machine use.
- Choose or create a route that makes sense for a machine client, for example:
GET /api/metricsGET /api/healthGET /api/snippets/export
- Introduce an environment variable such as
API_KEY. - Implement middleware (e.g.
requireApiKey) that:- Reads the
x-api-keyheader. - Compares it with
API_KEY. - Returns
401on missing/incorrect keys.
- Reads the
- Protect your machine-style route with this middleware.
If you have time, add a very simple in-memory rate-limiting mechanism (for example, per API key) and document the limitations of such an approach.
Add a short reflection section to your repository (for example in AUTH_NOTES.md) where you answer the following questions in a few sentences or bullet points each:
- Which auth mechanism would you choose for:
- A SPA web app with many users?
- A microservice-to-microservice communication scenario?
- An internal admin tool used by a small team?
- Why would you not use the other mechanisms in those scenarios?
- What is one security improvement you would like to make next if you had more time?
Continue progress on the Events Startup Project. Check the Weekly Plan for specific tasks to complete this week.