简体   繁体   中英

JSON Web TOken Strategy

This is passport function to extract headers. I am using fromAuthHeaderWithScheme one, I already tried fromAuthHeaderAsBearerToken with bearer token as well. I could not make it work no matter what?

const JwtStrategy = require('passport-jwt').Strategy,
      ExtractJwt = require('passport-jwt').ExtractJwt,
      User = require('../models/user'),
      Config = require('../config/database');


    module.exports = function(passport) {

      let opts = {};

      opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme("JWT");
      opts.secretOrKey = Config.secret;
      //Code only comes until here. 
      passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
        console.log(jwt_payload);//Code never reaches here.
        User.getByUserId({
          id: jwt_payload._id
        }, function(err, user) {
          if (err) {
            return done(err, false);
          }
          if (user) {
            return done(null, user);
          } else {
            return done(null, false);
          }
        });
      }));


    }

Next is my getUserById function

module.exports.getByUserId = function(id, cb) {
  User.findById(id, cb)
}

Next, is where above two gets called:

router.post('/login', function(req, res) {
  let username = req.body.username;
  password = req.body.password;

  User.getByUserName(username, function(err, user) {
    if (err) {
      throw err;
    }
    if (!user) {
      return res.json({
        success: "false",
        msg: "User not found"
      })
    }
    //if found compareUser to regiestred one
    User.comparePassword(password, user.password, function(err, isMatched) {
      if (err) {
        throw err;
      }
      if (isMatched) {
        const token = jwt.sign(user.toJSON(), CONFIG.secret, {
          expiresIn: 3600 /*Logout in 1 hour*/
        });

        res.json({
          success: "true",
          token: 'JWT ' + token,
          user: user._id,
          email: user.email,
          username: user.username,
        });
      } else {
        return res.json({
          success: "false",
          msg: " Password not Matched"
        });
      }
    });
  });
});

And these are comparePassword and getUserByName incase you need to see:

module.exports.comparePassword = function(typedPassword, hash, cb) {
  bcrypt.compare(typedPassword, hash, (err, isMatched) => {
    if (err) {
      throw err;
    }
    return cb(null, isMatched);
  })
};

module.exports.getByUserName = function(username, cb) {
  const query = {
    username: username
  }
  User.findOne(query, cb);
}

The secret key is same every where, that is not the issue. I cannot seem to figure out the issue.

router.get("/profile", passport.authenticate('jwt', {
  session: false
}, function(req, res, next) {
  res.json({
    success: true,
    message: "This is user profile",
    user: req.user
  });
}));

Now, above is how I authenticate, using postman and sending request as content type "Authorization" and The token. Encase, any of you are wondering, I already tried 'bearer '+token through bearer scheme.

I changed the first code block I posted above to this

 const JwtStrategy = require('passport-jwt').Strategy,
        ExtractJwt = require('passport-jwt').ExtractJwt,
        keys = require('./keys'),
        mongoose = require('mongoose'),
        User = require('../models/User');

    const opts = {};
    opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken('Bearer');
    opts.secretOrKey = keys.secretOrKey;


    module.exports = passport => {
        passport.use(new JwtStrategy(opts, (jwt_payload, done) => {
            User.findOne({ id: jwt_payload.sub }, (err, user) => {
                User.findById(jwt_payload.id)
                    .then(user => {
                        if (user) {
                            return done(null, user);
                        }
                        return done(null, false);
                    })
                    .catch(err => console.log(err));
            });
        }))
    };

And second block to this. Basically change the token from 'JWT' to 'Bearer'.

router.post('/login', (req, res) => {
    const email = req.body.email, password = req.body.password;
    User.findOne({ email: email })
        .then(user => {
            if (!user) {
                res.status(404).json({ msg: 'User not found' })
            }
            //Check password
            bcrypt.compare(password, user.password)
                .then(isMatch => {
                    if (isMatch) {
                        //User found
                        //Create Jwt Payload
                        const payload = {
                            id: user.id,
                            name: user.name,
                            avatar: user.avatar
                        }

                        jwt.sign(
                            payload,
                            keys.secretOrKey,
                            { expiresIn: 3600 },
                            (err, token) => {
                                res.json({
                                    success: true,
                                    token: 'Bearer ' + token
                                });
                            });
                    } else {
                        return res.status(400).json({ password: 'Password do not match' })
                    }
                })
            // .catch(err => console.log(err));

        })
});

Now its working for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM