Express.js, сервер отвечает Unauthorized, но пользователь авторизован
Проект(обучаюсь): https://github.com/mihinov/crm-angular
У меня есть index.js, в нём я подключаю основное приложение app.js
const app = require('./app');
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server has been started on http://localhost:${port}`));
app.js, подключение всех роутов:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const morgan = require('morgan');
const mongoose = require('mongoose');
const passport = require('passport');
const authRoutes = require('./routes/auth');
const analyticsRoutes = require('./routes/analytics');
const categoryRoutes = require('./routes/category');
const orderRoutes = require('./routes/order');
const positionRoutes = require('./routes/position');
const keys = require('./config/keys');
const app = express();
mongoose.connect(keys.mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
})
.then(() => console.log('MongoDB connected'))
.catch(err => console.error(err));
app.use(passport.initialize());
require('./middleware/passport')(passport);
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(cors());
app.use('/api/auth', authRoutes);
app.use('/api/analytics', analyticsRoutes);
app.use('/api/category', categoryRoutes);
app.use('/api/order', orderRoutes);
app.use('/api/position', positionRoutes);
module.exports = app;
/routes/auth.js:
const express = require('express');
const controller = require('../controllers/auth');
const router = express.Router();
router.post('/login', controller.login);
router.post('/register', controller.register);
module.exports = router;
/controllers/auth.js:
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('../models/User'); // модель пользователя
const keys = require('../config/keys');
const errorHandler = require('../utils/errorHandler');
module.exports.login = async function(req, res) {
const candidate = await User.findOne({email: req.body.email});
if (candidate) {
// Проверка пароля, пользователь существует
const passwordResult = bcrypt.compareSync(req.body.password, candidate.password);
if (passwordResult) {
// Генерация токена, пароли совпали
const token = jwt.sign({
email: candidate.email,
userId: candidate._id
}, keys.jwt, {expiresIn: 60 * 60});
res.status(200).json({
token: `Bearer ${token}`
});
} else {
// Пароли не совпали
res.status(401).json({
message: 'Пароли не совпадают, пробуйте снова'
});
}
} else {
// Пользователя нет, ошибка
res.status(404).json({
message: 'Пользователь с таким Email не найден'
})
}
};
module.exports.register = async function(req, res) {
const candidate = await User.findOne({email: req.body.email});
if (candidate) {
// Пользователь существует, нужно отдать ошибку
res.status(409).json({
message: 'Такой Email уже занят, попробуйте другой'
});
} else {
// Нужно создать пользователя
const salt = bcrypt.genSaltSync(10);
const password = req.body.password
const user = new User({
email: req.body.email,
password: bcrypt.hashSync(password, salt)
});
try {
await user.save();
res.status(201).json(user);
} catch(e) {
// Обработать ошибку
errorHandler(res, e);
}
}
};
Использую приложение Postman для отправки http запросов на сервер.
Регистрирую пользователя, обращаясь к POST http://localhost:5000/api/auth/register
Авторизуюсь, обращаясь к POST http://localhost:5000/api/auth/login, мне выдаётся токен
Пытаюсь обратиться к GET http://localhost:5000/api/category, получить категории, отправляю ключ Authorization в Header, в который я ввёл токен, который мне выдался при регистрации, но получаю ответ Unathorized
Роуты категорий: routes/category.js:
const express = require('express');
const passport = require('passport');
const upload = require('../middleware/upload');
const controller = require('../controllers/category');
const router = express.Router();
router.get('/', passport.authenticate('jwt', {session: false}), controller.getAll);
router.get('/:id', passport.authenticate('jwt', {session: false}), controller.getById);
router.delete('/:id', passport.authenticate('jwt', {session: false}), controller.remove);
router.post('/', passport.authenticate('jwt', {session: false}), controller.create);
router.patch('/:id', passport.authenticate('jwt', {session: false}), upload.single('image'), controller.update);
module.exports = router;
/controllers/category.js, использую метод getAll, для получения всех записей:
const Category = require('../models/Category');
const Position = require('../models/Position');
const errorHandler = require('../utils/errorHandler');
module.exports.getAll = async function(req, res) {
try {
const categories = await new Category.find({user: req.user.id});
res.status(200).json(categories);
} catch(e) {
errorHandler(res, e);
}
};
middleware/passport.js:
const passportJwt = require('passport-jwt');
const JwtStrategy = passportJwt.Strategy;
const ExtractJwt = passportJwt.ExtractJwt;
const keys = require('../config/keys');
const mongoose = require('mongoose');
const User = mongoose.model('users');
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken,
secretOrKey: keys.jwt
};
module.exports = passport => {
passport.use(
new JwtStrategy(options, async (payload, done) => {
try {
const user = await User.findById(payload.userId).select('email id');
if (user) {
done(null, user);
} else {
done(null, false);
}
} catch(e) {
console.error(e);
}
})
)
};
Ответы (1 шт):
Я забыл вызвать функцию ExtractJwt.fromAuthHeaderAsBearerToken
В файле /middleware/pasport.js объект options был такой:
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken,
secretOrKey: keys.jwt
};
А надо было:
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: keys.jwt
};


