Authentication and authorization of a client web application using a remote NodeJS API that uses Passport.js

As shown in the figure below, I have a standalone API project running on a server with say port 3001, and I have a web application running on a server with say port 3002.

API Web Application Flow

The API on port 3001 has all the API routes necessary for a web application (& mobile applications) to retrieve and host data, including authentication APIs (using passport-localand passport-jwt). As a part of the project’s API, I also processed user role authorization, and on each route there is A list of roles that can access the API.

Route Example

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

Role Authorization API Method on 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');

        });
    }
}

json

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

-, (), , - , , , , , , .

, :

  • - Remote API 3001 ()
  • (, ) ()
  • , -, loggedin, . API 3002, .

+2
4

API JWT (). , , API-.


, npm jsonwebtoken, :

token = jwt.sign( {
    exp: Math.floor( Date.now() / 1000 ) + ( 60 * 60 ), // 1 hour
    i: user._id,
    role: user.role
}, "my-secret" );

API passport-jwt, , . :

passport.use( new JwtStrategy( {
    secretOrKey: "my-secret"

}, ( payload, callback ) => callback( null, payload ) ) );

const authenticate = () =>
    passport.authenticate( "jwt", { session: false, failWithError: true } )

. , :

const assertRole = ( ...roles ) => ( req, res, next ) => 
    req.user && roles.includes( req.user.role ) ? next() : res.sendStatus( 403 ) );

todoRoutes.get("/admin/view1", authenticate, assertRole( "user", "editor", "admin" ), TodoController.getTodos );

, API , JWT (, , ), ( , ).

+1
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');

    });
}

}

0

, , .

api . , Unauthorized/Forbidden, . , .

, , admin/dashboard users/dashboard, , , . user.role. url , API.

, , .

, .

0

Is beauty JWTnot already solved, or, rather, can solve your problem with the correct implementation?

All you need is

  • initialize the module passport-jwtin WebApp in the same way as you initialize it in the API , namely in the parameter secretOrKey.
  • check JWT, namely the property roleand allow / reject based on this
0
source

All Articles