0
votes

On a server side I have 2 middlewares - protect (is logged in?) and restrictTo (checks user's role). These middlewares stop users or guests from performing certain actions if they are not allowed to

exports.protect = catchAsync(async (req, res, next) => {
  let token;

  if (
    req.headers.authorization && req.headers.authorization.startsWith("Bearer")
  ) {
    token = req.headers.authorization.split(" ")[1];
  }

  if (!token) {
    return next(new AppError("You are not signed in!", 401));
  }

  const decodedToken = await promisify(jwt.verify)(
    token,
    process.env.JWT_SECRET
  );

  const currentUser = await User.findById(decodedToken.id);
  if (!currentUser) {
    return next(new AppError("User with such token no longer exists"));
  }

  req.user = currentUser;
  next();
});


exports.restrictTo = (...roles) => {
  return (req, res, next) => {
    if (!roles.includes(req.user.role)) {
      return next(new AppError("No access", 403));
    }
    next();
  };
};

But how do I protect routes on a client side? If I'm not allowed to post a new note then I should be stopped from going to a /newnote page so I can't see and fill the form. JWT token is stored in cookies with httpOnly flag. So I can't access the token from a Vue router. Store a user's role in Vuex? Then how do I synchronize the token state in cookies and in Vuex? If my token has been destroyed on a server side I still can have it in Vuex until I send a request to a protected endpoint. Should I request a special auth endpoint for protected routes to check my current role using beforeEach?

1

1 Answers

1
votes

Basically, you should add two things:

  • store the current authenticated user. By default, authUser is null. When someone logs in, authUser is an object with the user’s data. you can store this in Vuex, localStorage, etc.
  • create an interceptor/middleware in whatever library you are using for your api requests. If at some point you get a 401/403, it means that the current user’s session expired, or he is trying to access a protected area he shouldnt be looking at. Either way, reset the local authUser to null and redirect to login.

In Spa/mobile you dont have to worry too much about this as long as your backend is properly secured. If your authUser logic is correct, then only users with bad intentions will try to reach protected areas, whereas normal users will play by the rules and never hit a page they arent supposed to with their current privileges (assuming the UI is wired up correctly…).