3

I am trying to get the user id so I can connect models in mongoose and keep track of what each user has posted. But in order to do that I need to get the user id from jwt token and I have no idea how. This is a MERN application and I have tried to get the id in the from from react but unsuccessfully. Here is my code:

Authentication with jwt

const express = require("express");
const router = express.Router();
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const util = require("util");

const passwordHash = require("../../config/passwordHash")
//get middleware
const authenticateUser = require("../middleware/authenticateUser");
const validateBodyWith = require("../middleware/validateUserWith");

//data validators
const { loginValidator, registerValidator } = require("../validation");
//load User model
const { User } = require("../../models");

const jwtSign = util.promisify( jwt.sign );

//get currently validated user
router.post("/authenticated", authenticateUser, (req,res)=>{
  // console.log(req.user);
  res.json(req.user);
});

 //log in an existent user by signing and returning a secure json web token
 // for the client application to store and include with requests

router.post("/login", validateBodyWith(loginValidator), async(req,res)=>{
 
  const {email,password} = req.body;
  console.log(req.body);

  try{
    const user = 
      await User
      .findOne({email})
      // .populate('records');
    if(!user){
      //user not found by email
      return res.status(404).json({default:"your email or password is invalid"})
    }
  
    const {
      password: encryptedPassword,
      // User object without the password
      ...secureUser
    } = user._doc;
    console.log("user----:",secureUser)

    const isMatch = await bcrypt.compare( password, encryptedPassword );
    
    if( !isMatch ) {
      // User's password is invalid.
      return res.status(404).json({ default: "Email or password is invalid." });
    }

    const payload = {
      id:secureUser._id,
      email:secureUser.email
    };
    console.log(payload);
    //create a signed web token to send back to the client for reauthentication
    const token =  await jwtSign(
      payload,
      process.env.JWT_SECRET,
      {
        expiresIn:31556926 //one year in seconds
      }
    );

    return res.json({
      sucess:true,
      token: "Bearer " + token,
      user:secureUser
    })
  }catch(err){

    console.log(err);
    res.status(500).json({default:"something went wrong trying to log in "})
  }

});

// creates a new user for authentication 

router.post("/register", validateBodyWith(registerValidator), async(req,res)=>{
  console.log(req.body)
  try{
    const { name, email, password } = req.body;

    const user = await User.findOne({ email });

    if (user) {
      // User already exists error.
      return res.status(400).json({ email: "Email already exists." });
    }

    const newUser = new User({
      name,
      email,
      password: await passwordHash( password )
    });

    await newUser.save();

    const {
      password: encryptedPassword,
      // User object without the password
      ...secureUser
    } = newUser._doc;

    res.json( secureUser );

  }catch(err){
    console.log(err);
    res.status(500).json({ default: "Something went wrong creating your account." });

  }

});
module.exports = router; 

Middleware :

const passport = require('passport');

const authenticateUser = passport.authenticate('jwt',{session:false});

module.exports = authenticateUser;
const mapValidationErrors = errors => errors.reduce( (errors, {field, message}) => ({ ...errors, [field]: message }), {} );

const validateBodyWith = validator => ( req, res, next ) => {

    const result = validator( req.body );

    // Body data valid! Continue to the next step...
    if( true === result ) return next();

    // Validation failed! Send and error response.
    res.status(400).json( mapValidationErrors(result) );

}

module.exports = validateBodyWith;
const validatorFactory = require("./validatorFactory");

const loginValidator = validatorFactory({
  email: { type: "email" },
  password: { type: "string", empty: false }
});

module.exports = loginValidator;
const validatorFactory = require("./validatorFactory");

const registerValidator = validatorFactory({
  name:{type:"string", empty:false},
  email: { type: "email" },
  password: { type: "string", empty: false }
  
});

module.exports = registerValidator;
const Validator = require("fastest-validator");
const  { ObjectID } = require("mongodb");

const v = new Validator({
  defaults: {
      objectID: {
          ObjectID
      }
  }
});

const validatorFactory = schema => v.compile({
  $$strict: "remove",
  ...schema
});

module.exports = validatorFactory;

1 Answers1

0

If you use passport, then your user's id can be retrieved from req.user.id

I will recommend you to do a detail reading @ http://www.passportjs.org/packages/passport-jwt/ since you can either pass the JWT code from Client Side to Server Side from Authorization header, or cookie.

Include the JWT in requests

The strategy will first check the request for the standard Authorization header. If this header is present and the scheme matches options.authScheme or 'JWT' if no auth scheme was specified then the token will be retrieved from it. e.g.

Authorization: JWT JSON_WEB_TOKEN_STRING..... If the authorization header with the expected scheme is not found, the request body will be checked for a field matching either options.tokenBodyField or auth_token if the option was not specified.

Finally, the URL query parameters will be checked for a field matching either options.tokenQueryParameterName or auth_token if the option was not specified.

Someone Special
  • 12,479
  • 7
  • 45
  • 76