Search code examples
reactjspassport.jspassport-jwt

how can I properly protect all my routes using passport and passport-jwt


I built this react app and am using passport-local to authenticate the Admin as well as the users. I have been able to follow some tutorials and authenticate the users. Now that I would like to implement jwt to protect some routes, I don't seem to make it work. Using Postman, I can sign up, and also login, and I get a token back. But when I try the protected routes I get a 401 Unauthorized response. Any help with this will be greatly appreciated.

I have been able to follow some tutorials and authenticate the users. Now that I would like to implement jwt to protect some routes, I don't seem to make it work. Using Postman, I can sign up, and also login, and I get a token back. But when I try the protected routes I get a 401 Unauthorized response. Any help with this will be greatly appreciated.

const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJWT = require('passport-jwt').ExtractJwt;
const config = require('./secret');

// const salt = bcrypt.genSaltSync(10);


module.exports = (userType, passport) => {
    const opts = {
        jwtFromRequest: ExtractJWT.fromAuthHeaderWithScheme('JWT'),
        secretOrKey: config.secret,
    };

passport.use('jwt', new JwtStrategy(opts, (jwt_payload, done) => {
    try {
        User.findOne({
            where: {
                id: jwt_payload.id,
            },
        }).then(user => {
            if (user) {
                console.log('user found in db in passport');
                done(null, user);
            } else {
                console.log('user not found in db');
                done(null, false);
            }
        });
    } catch (err) {
        done(err);
    }
})
)

passport.use(
    'login',
    new LocalStrategy(
        {
            usernameField: 'username',
            passwordField: 'password',
            session: false,
        },
        (username, password, done) => {
            try {
                User.findOne({
                    where: {
                        username,
                    },
                }).then(user => {
                    if (user === null) {
                        return done(null, false, { message: 'bad username' });
                    }
                    bcrypt.compare(password, user.password).then(response => {
                        if (response !== true) {
                            console.log('passwords do not match');
                            return done(null, false, { message: 'passwords do not match' });
                        }
                        console.log('user found & authenticated');
                        return done(null, user);
                    });
                });
            } catch (err) {
                done(err);
            }
        },
    ),
);

this is how I'm trying to protect routes:

 router.get('/api/clients', (req, res, next) => {
passport.authenticate('jwt', { session: false }, (err, user, info) => {
    if (err) {
        console.log(err);
    }
    if (info !== undefined) {
        console.log(info.message);
        res.status(401).send(info.message);
    } else if (user.username === req.query.username) {
        User.findOne({
            where: {
                username: req.query.username,
            },
        }).then((userInfo) => {
            if (userInfo != null) {
                console.log('user found in db');
                res.status(200).send({
                    auth: true,
                    // first_name: userInfo.first_name,
                    // last_name: userInfo.last_name,
                    email: userInfo.email,
                    username: userInfo.username,
                    password: userInfo.password,
                    message: 'user found in db',
                });
                db.Client.findAll({}).then(function (dbClient) {
                    res.json(dbClient);
                });
            } else {
                console.error('no user exists in db with that username');
                res.status(401).send('no user exists in db with that username');
            }
        });
    } else {
        console.error('jwt id and username do not match');
        res.status(403).send('username and jwt token do not match');
    }
})(req, res, next);

});


Solution

  • I could solve it by simplifying the protected route like this:

     app.get('/auth/api/clients', 
    passport.authenticate('jwt', {
    session: false
      }), (req, res) => {
    
    console.log(req.user);
    // console.log(res)
    return (db.Client.findAll({}).then(function 
    (dbClient) {
      if (typeof dbClient === "object") {
        res.json(dbClient);
         }
       }
       ));
      });
    

    Now everything works perfectly.