How to Authenticate & Authorize a Client-Side Web App using Remote NodeJS API that uses Passport.js

As shown in the illustration below, I have a standalone API Project running on a server with a port say 3001, and I have a Web App running on a server with port say 3002.

API on port 3001, has all the API routes required for the Web App (& mobile apps) to fetch and put data, including Authentication API (Using passport-local and passport-jwt). In the API side of the project, I have also handled user role authorization, and every routes has list of roles who can access the APIs.

Example Route

todoRoutes.get('/', 
               requireAuth,
               AuthController.roleAuth(['user','editor','admin']),
               TodoController.getTodos);

Role Authorization API Method in port 3001

exports.roleAuth = function(roles){

    return function(req, res, next){

        var user = req.user;

        User.findById(user._id, function(err, foundUser){

            if(err){
                res.status(422).json({error: 'No user found.'});
                return next(err);
            }

            if(roles.indexOf(foundUser.role) > -1){
                return next();
            }

            res.status(401).json({error: 'You are not authorized to view this content'});
            return next('Unauthorized');

        });
    }
}

Response json after login successfully is like this

{
    "token": "JWT eyJhbGci...",
    "user": {
        "_id": "5986b81d940bab06ddc79b34",
        "email": "myemail@gmail.com",
        "role": "admin"
    }
}

Now in Web App, I want to use same role authorization and authentication (login), but you see, Web App is not connected to database, for me to make queries like check if the user in session is valid and has the role as in the response it got after login successfully.

Summary
Here are bullet points of what I was looking for in this question:

  1. Login on Client-Side Web Application, via Remote API on port 3001 (achieved)
  2. Get User Token and other information (response shown above) (achieved)
  3. Ensure user is authenticated on Client-Side Web App and also remember role of the user loggedin, to use these information for authorization of every routes on Client-side app. In client-side app I have few pages with forms to send data to Server-Side API on port 3002, these pages are used by two different user with roles editor and admin.

TIA

exports.roleAuth = function(roles){

return function(req, res, next){

    var user = req.user;

    User.findById(user._id, function(err, foundUser){

        if(err){
            res.render('index.html');
        }

        if(roles.indexOf(foundUser.role) > -1){
            res.render('another.html');
        }

        res.render('another2.html');

    });
}

}

There are two ways that I see this can be done, though not perfectly.

One is to use the primary api endpoint of a particular view. Normally each view has a primary endpoint, and if that endpoint returns an Unauthorized / Forbidden status, you shouldn’t render the view. But this solution has problems and not always there’s a primary endpoint matching a view.

Other option is to namespace the routes with roles, like admin/dashboard and users/dashboard, and the user should have a field describing their role, eg. user.role. And before rendering the views, check for the respective role in url and in user object returned by the API.

The second option is preferred and this is what I generally use.

Hope it helps.