In this part, you will add JWT-based authentication to the Snippets API on top of the secure /login flow you built earlier.
We will:
- Issue a JWT after a successful login.
- Validate the JWT on protected routes.
- Use it to guard important Snippets API endpoints.
Conceptual note: a JWT is just a signed JSON object. It usually contains a user identifier (for example
userId), but it does not have to be tied to a user – it’s up to you what claims you put inside. The server uses a shared secret (JWT_SECRET) to sign and later verify that the token is genuine and has not expired.
- Install the
jsonwebtokenpackage in your Snippets API project. - Decide on a
JWT_SECRETvalue (for local development you can use an environment variable or a hardcoded string). In production, clients must never know this secret – only the server should be able to issue valid tokens.
Re-use your secure /login route:
- After verifying the password with bcrypt, generate a JWT with a payload like
{ userId: user.id }:- This “binds” the token to that user account.
- You can also include other claims if needed (for example roles or scopes).
- Set a reasonable expiration time (for example 1 hour) using
expiresIn. After this time,jwt.verifywill treat the token as expired. - Return the token in the JSON response (for example
{ "token": "<jwt-here>" }).
In Postman or a frontend app, you typically store the token on the client and then send it on each request in an Authorization: Bearer <token> header.
Create a middleware function (for example in middleware/auth-jwt.js) that:
- Reads the
Authorizationheader, expectingBearer <token>. - Uses
jwt.verify(token, JWT_SECRET)to:- Check that the token was signed with your secret.
- Check that it has not expired (
expclaim).
- Attaches the decoded user information to
req.user(for examplereq.user = { id: decoded.userId }). - Sends a
401response if the token is missing, invalid, or expired.
Choose at least two endpoints in your Snippets API (for example):
POST /api/snippetsDELETE /api/snippets/:id
Wrap these handlers with your JWT auth middleware so that:
- Requests without a valid token are rejected with
401and a suitable JSON error. - Requests with a valid token are allowed to proceed.
For this session, it is enough to have a single short-lived JWT that the client includes on each request:
- When the token is valid and not expired, protected routes work as normal.
- When the token has expired, your middleware returns
401and the client can prompt the user to log in again to obtain a new token.
Out in the real world, applications often add extra layers:
- Refresh tokens: a short-lived JWT (access token) plus a longer-lived refresh token that can be used to get a new access token without asking the user to log in again immediately.
- Revocation / logout: because JWTs are stateless, revoking them early usually means keeping some server-side state (for example a list of revoked token IDs or “logout timestamps” per user) and checking that state inside your JWT middleware.
These are useful extensions to think about, but for this session you can focus on the basic, stateless flow described above.