У меня было чертовски много времени с паспортом и jwt. Итак, вот что я понял, что мне нужно сделать, чтобы получить req.user в своих маршрутах. Я, конечно, знал, что мне нужно промежуточное ПО, но какое???

// middleware to test user authentication and set in req.user
function verifyUser(req, res, next) {
  passport.authenticate('jwt', { session: false }, (err, user, info) => {
    if (err || !user) {
      return res.status(400).json({
        message: info.message
      });
    }
    req.user = user;
    next()
  })(req, res, next);
}

И затем в моих маршрутах:

app.use("/api/invoices", verifyUser, invoices);

Просто чтобы охватить все основы, мой файл конфигурации паспорта выглядит так:

const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const mongoose = require('mongoose');
const User = require('../models/User');
const keys = require('../config/keys');
const options = {};
options.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
options.secretOrKey = keys.secretOrKey;
module.exports = passport => {
  passport.use(new JwtStrategy(options, (payload, done) => {
    User.findById(payload.id)
      .then(user => {
        if (user) {
          return done(null, user);
        } else {
          return done(null, false);
        }
      })
      .catch(err => console.log(err))
  }));
};

и мой файл server.js:

const mongoose = require('mongoose');
const express = require("express");
const app = express();
const path = require('path');
const morgan = require('morgan');
const db = require('./config/keys').mongoURI;
mongoose
  .connect(db, { useNewUrlParser: true })
  .then(() => console.log("Connected to MongoDB successfully"))
  .catch(err => console.log(err));
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// setup logger
app.use(morgan('dev'));
const passport = require('passport');
app.use(passport.initialize());
require('./config/passport')(passport);
// setup static folder for frontend
app.use(express.static( `${__dirname}/frontend/build`));
// router routes
const users = require("./routes/api/users");
const invoices = require("./routes/api/invoices");
const clients = require("./routes/api/clients");
const subs = require("./routes/api/subscriptions");
// middleware to test user authentication and attach user as req.user
function verifyUser(req, res, next) {
  passport.authenticate('jwt', { session: false }, (err, user, info) => {
    if (err || !user) {
      return res.status(400).json({
        message: info.message
      });
    }
    req.user = user;
    next()
  })(req, res, next);
}
app.get("/", (req, res) => res.send(""));
app.use("/api/users", users);
app.use("/api/invoices", verifyUser, invoices);
app.use("/api/clients", verifyUser, clients);
app.use("/api/subscriptions", verifyUser, subs);
// serve up index.html for frontend
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, '/frontend/build/index.html'));
});
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server is running on port ${port}`));

И мои маршруты входа и регистрации:

const express = require("express");
const router = express.Router();
const bcrypt = require('bcryptjs');
const User = require('../../models/User');
const jwt = require('jsonwebtoken');
const keys = require('../../config/keys');
const passport = require('passport');
const validateRegisterInput = require('../../validation/register');
const validateLoginInput = require('../../validation/login');
router.post('/register', (req, res) => {
  const { errors, isValid } = validateRegisterInput(req.body);
if (!isValid) {
    return res.status(400).json(errors);
  }
User.findOne({ email: req.body.email })
    .then(user => {
      if (user) {
        // errors.name = "User already exists";
        return res.status(400).json({ email: "A user has already registered with this address"})
      } else {
        const newUser = new User(req.body);
        // don't store plaintext password
        bcrypt.genSalt(10, (err, salt) => {
          bcrypt.hash(newUser.password, salt, (err, hash) => {
            if (err) throw err;
            newUser.password = hash;
            newUser
              .save()
              .then(user => {
                const payload = { id: user.id, name: user.name };
jwt.sign(payload, keys.secretOrKey, { expiresIn: 86400 * 7 }, (err, token) => {
                  res.json({
                    success: true,
                    token: "Bearer " + token
                  });
                });
              })
              .catch(err => console.log(err));
          });
        });
      }
    });
})
router.post('/login', (req, res) => {
  const { errors, isValid } = validateLoginInput(req.body);
if (!isValid) {
    return res.status(400).json(errors);
  }
const email = req.body.email;
  const password = req.body.password;
User.findOne({email})
    .then(user => {
      if (!user) {
        errors.name = "This user does not exist";
        return res.status(404).json({email: 'This user does not exist'})
      }
bcrypt.compare(password, user.password)
        .then(isMatch => {
          if (isMatch) {
            const payload = { id: user.id, name: user.name };
jwt.sign(payload, keys.secretOrKey, {expiresIn: 3600 }, (err, token) => {
              res.json({
                success: true,
                token: 'Bearer ' + token
              });
            });
          } else {
            errors.password = "Incorrect password";
            return res.status(400).json({password: 'Incorrect password'});
          }
        })
    })
})

Решение проблемы так же хорошо, как и эти сексуальные чувства… иногда, ладно, а может и нет. Прямо из Морган Хилл, Калифорния. Удачи!

Стивен Ласерда