Шифровать Nodejs JWT токен - PullRequest
       132

Шифровать Nodejs JWT токен

0 голосов
/ 03 апреля 2020

Я следовал руководству по созданию тестового приложения API из этой статьи . В конце статьи я вижу упоминание о том, что лучше всего шифровать токен jwt для дополнительной безопасности, поэтому я также искал способ сделать это. Я наткнулся на эту статью , и в ней приведены примеры того, как зашифровать токен jwt с помощью закрытых / publi c ключей RSA.

Вот где я застреваю. После того, как я успешно зарегистрировался, используя маршрут / signup, я могу использовать маршрут / login, чтобы получить свой токен. Итак, я предполагаю, что именно здесь я использую свой закрытый ключ для шифрования токена перед отправкой его пользователю?

** Сделано репо publi c для тестирования - вам понадобится только чтобы предоставить строку соединения mongoDB в приложении. js

Я застрял в части процесса шифрования / дешифрования, любая помощь приветствуется.

router.post("/login", async (req, res, next) => {
  passport.authenticate("token", async (err, user, info) => {
    try {
      if (err || !user) {
        const error = new Error("An Error occurred");
        return next(error);
      }
      req.login(user, { session: false }, async error => {
        if (error) return next(error);
        //We don't want to store the sensitive information such as the
        //user password in the token so we pick only the email and id
        const body = { _id: user._id, email: user.email };
        //Sign the JWT token and populate the payload with the user email and id
        const token = jwt.sign({ user: body }, PRIV_KEY, { algorithm: 'RS256' });
        //Send back the token to the user
        return res.json({ token });
      });
    } catch (error) {
      return next(error);
    }
  })(req, res, next);
});

А затем при вызовах «безопасные» маршруты, мне нужно расшифровать токен и verify против ключа publi c?

router.get("/profile", (req, res, next) => {
  //We'll just send back the user details and the token

  jwt.verify(req.query.token, PUB_KEY, { algorithms: ['RS256'] }, function(err, decoded) {
    if (err.name === "TokenExpiredError") {
      console.log("Whoops, your token has expired!");
    }

    if (err.name === "JsonWebTokenError") {
      console.log("That JWT is malformed!", err); <------ GET ERROR HERE
    }

    if (err === null) {
      console.log("Your JWT was successfully validated!");
    }

    // Both should be the same
    console.log(decoded);
    res.json({
      message: "You made it to the secure route",
      user: req.user
    });
  });
});

1 Ответ

1 голос
/ 03 апреля 2020

У меня нет времени, чтобы воспроизвести это. Ваша учетная запись выглядит правильно. Тем не менее, вы должны попытаться настроить защищенные маршруты, подобные этому, скопированные и адаптированные к вашим потребностям из первой статьи:

Настройка промежуточного программного обеспечения для обработки дешифрования jwt, обязательно укажите его в вашем app.js или где бы вы ни находились нужно, если вы настроили его в отдельный файл. Это может быть использовано в качестве промежуточного программного обеспечения позже в ваших контроллерах:

const JWTstrategy = require('passport-jwt').Strategy;
//We use this to extract the JWT sent by the user
const ExtractJWT = require('passport-jwt').ExtractJwt;

//This verifies that the token sent by the user is valid
passport.use(new JWTstrategy({
  //secret we used to sign our JWT
  secretOrKey : PUB_KEY,
  algorithms: ['HS256'],
  //we expect the user to send the token as a query parameter with the name 'token'
  jwtFromRequest : ExtractJWT.fromUrlQueryParameter('token')
}, async (token, done) => {
  try {
    //Pass the user details to the next middleware
    return done(null, token.user);
  } catch (error) {
    done(error);
  }
}));

Настройка защищенного маршрута, обратите внимание, что вам не нужно вручную вызывать jwt.verify, промежуточное программное обеспечение обрабатывает его и заполняет req.user:

const express = require('express');

const router = express.Router();

//Let's say the route below is very sensitive and we want only authorized users to have access

//Displays information tailored according to the logged in user
router.get('/profile', passport.authenticate('jwt', { session: false }), (req, res, next) => {
  //We'll just send back the user details and the token
  res.json({
    message : 'You made it to the secure route',
    user : req.user,
    token : req.query.token
  })
});

module.exports = router;

** Обновление на основе вашего комментария:

Я клонировал ваш репозиторий, и он работает для меня, хотя я кое-что изменил:

  • Я добавил app.use(bodyParser.json()); к app.js, чтобы можно было отправлять тела запросов как json - в этом нет необходимости, если вы предпочитаете urlencoded

  • , проблема в том, что secureRoute вы экспортируете другой маршрутизатор, и вы попытаетесь использовать его в качестве контроллера в app.js:

...
const secureRoute = require('./routes/secure-routes');
...
app.use('/user', passport.authenticate('jwt', { session: false }), secureRoute);`

* обратите внимание, что это будет /user маршрут, если вы хотите /profile измените его, как app.use('/profile', ...)

, поэтому вместо

router.get("/profile", (req, res, next) => {
  //We'll just send back the user details and the token
  res.json({
    message: "You made it to the secure route",
    user: req.user,
    token: req.query.secret_token
  });
});

это должна быть просто функция контроллера:

...
module.exports = (req, res, next) => {
  //We'll just send back the user details and the token
  res.json({
    message: 'You made it to the secure route',
    user: req.user,
    token: req.query.token // note that you don't use secret_token but token as a name
  });
};
  • третий нужно не забыть добавить токен в параметры запроса, когда вы вызываете API, например, http://localhost:3000/user?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7Il9pZCI6IjVlODc2Yjc1YTVlNTk3MTRlOGFjMmI4NyIsImVtYWlsIjoiYUBiLmNvbSJ9LCJpYXQiOjE1ODU5MzMyNjR9.lcLuQeCMRy7Ef9zNkIt_rn4S22t2cm7YLRE7Jgp1Mpw

, вы должны получить ответ se:

{
    "message": "You made it to the secure route",
    "user": {
        "_id": "5e876b75a5e59714e8ac2b87",
        "email": "a@b.com"
    }
}
...