Skip to content

Token Routes Documentation

This section provides a detailed breakdown of the token management API routes, specifically focusing on refreshing authentication tokens. The documentation outlines the purpose of the route, the flow of requests through middleware, controllers, and services, and the expected responses.


1. Refresh Tokens

Endpoint: POST /v1/token/refresh Description: Refreshes an expired access token using a valid refresh token. This route issues a new access token and a new refresh token.

Flow Map

  1. Initial Request:
  2. Method: POST
  3. Path: /v1/token/refresh
  4. Client Sends:
  5. Cookie: refreshToken=<jwt-refresh-token> (an HTTP-only cookie containing the refresh token).
  6. No request body or parameters.

  7. Route Handler (src/api/token.routes.ts):

    router.post('/refresh', validate(authValidation.refreshTokens), tokenController.refreshTokens);
    

  8. The request first passes through the validate(authValidation.refreshTokens) middleware. This middleware uses the Zod schema defined in authValidation.refreshTokens to ensure a refreshToken cookie is present.
  9. If validation passes, the request is forwarded to tokenController.refreshTokens.

  10. Controller (src/controllers/token.controller.ts):

    const refreshTokens = async (req: Request, res: Response, next: NextFunction) => {
      try {
        const { refreshToken } = req.cookies;
        if (!refreshToken) throw new ApiError(400, 'No refresh token provided');
        const tokens = await tokenService.refreshAuthTokens(refreshToken);
        res.cookie('refreshToken', tokens.refresh.token, {
          httpOnly: true,
          expires: tokens.refresh.expires,
        });
        res.send({ access: tokens.access });
      } catch (error) {
        next(error);
      }
    };
    

  11. The controller extracts the refreshToken from req.cookies.
  12. It performs a check to ensure the refreshToken exists. If not, it throws an ApiError (400 Bad Request).
  13. It calls tokenService.refreshAuthTokens() with the extracted refresh token.
  14. Upon successful token refresh, it sets a new refreshToken as an HTTP-only cookie with its new expiration.
  15. It sends a 200 OK response with a JSON object containing the new access token.
  16. Any errors are caught and passed to the Express error handling middleware.

  17. Service (src/services/token.service.ts):

  18. tokenService.refreshAuthTokens(refreshToken):
    const refreshAuthTokens = async (refreshToken: string) => {
      try {
        const refreshTokenPayload = verifyToken(refreshToken) as jwt.JwtPayload;
        const user = await prisma.user.findUnique({ where: { id: refreshTokenPayload.sub } });
        if (!user) {
          throw new ApiError(httpStatus.UNAUTHORIZED, 'Invalid refresh token');
        }
    
        await prisma.refreshToken.delete({ where: { token: refreshToken } }); // Delete old refresh token
        return generateAuthTokens(user); // Generate new access and refresh tokens
      } catch (error) {
        const errorStack = error instanceof Error ? error.stack : undefined;
        throw new ApiError(httpStatus.UNAUTHORIZED, 'Invalid refresh token', true, errorStack);
      }
    };
    
  19. Calls verifyToken() to validate the provided refreshToken. If invalid, it throws a 401 Unauthorized error.
  20. Extracts the userId (sub) from the refresh token's payload.
  21. Retrieves the user from the database using prisma.user.findUnique(). If the user is not found, it throws a 401 Unauthorized error.
  22. Deletes the old refresh token from the RefreshToken Prisma model in the database, ensuring it cannot be reused.
  23. Calls generateAuthTokens(user) to create a brand new access token and a new refresh token.
  24. Returns an object containing the new access and refresh tokens, each with their token string and expiration date.

  25. Response to Client:

  26. Status: 200 OK
  27. Body (JSON):
    {
      "access": {
        "token": "new-jwt-access-token",
        "expires": "2023-01-01T12:30:00.000Z"
      }
    }
    
  28. Cookie: refreshToken=new-jwt-refresh-token; HttpOnly; Expires=...
  29. Error Responses:
  30. 400 Bad Request: If no refresh token is provided in the cookie.
  31. 401 Unauthorized: If the refresh token is invalid, expired, or the associated user is not found.
  32. 500 Internal Server Error: For unexpected server-side errors.