@sasha_jarvi

Как решить проблему с авторизацией через passport.js в MEVN-приложении (ошибка 401)?

Работаю над MEVN-приложением, решил добавить авторизацию через passport.js. Регистрация и авторизация выполняются успешно, однако при попытке редиректа на домашнюю страницу после авторизации возникает ошибка 401 Unauthorized. JWT-токен в заголовке Authorization AJAX-запроса на домашней странице передаю, но безрезультатно. Вот код server.js:

const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const cors = require('cors');
const morgan = require('morgan');
const fs = require('fs');

const jwt = require('jsonwebtoken');
const passport = require('passport');
const passportJWT = require('passport-jwt');
const ExtractJWT = passportJWT.ExtractJwt;
const JWTStrategy = passportJWT.Strategy;
const jwtOptions = {};
jwtOptions.jwtFromRequest = ExtractJWT.fromAuthHeaderWithScheme('jwt');
jwtOptions.secretOrKey = 'movieratingapplicationsecretkey';

const app = express();
const router = express.Router();

const User = require('./models/User');

app.use(morgan('combined'));
app.use(bodyParser.json());
app.use(cors());
app.use(passport.initialize());

passport.use(new JWTStrategy(jwtOptions, (jwt_payload, done) => {
  User.findOne({ id: jwt_payload.id }, (err, user) => {
    if (err) {
      return done(err, false);
    }

    if (user) {
      return done(null, user);
    } else {
      return done(null, false);
    }
  });
}));

mongoose.connect('mongodb://localhost/movie_rating_app', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
})
  .then(() => {
    console.log('Connection is established');
  })
  .catch((err) => {
    console.error(`App starting error: ${err.stack}`);
  });

// include controllers
fs.readdirSync('controllers').forEach(file => {
  if (file.substr(-3) === '.js') {
    const route = require(`./controllers/${file}`)
    route.controller(app)
  }
})

router.get('/', (req, res) => {
  res.json({ message: 'API was initialized!' });
});

const port = process.env.API_PORT || 8081;
app.use('/', router);

app.listen(port, () => {
  console.log(`api running on port ${port}`);
});


Код controllers/movies.js:

const Movie = require('../models/Movie')
const Rating = require('../models/Rating')

const passport = require('passport')

module.exports.controller = app => {
  // fetch all movies
  app.get(
    '/movies',
    passport.authenticate('jwt', { session: false }),
    (req, res) => {
      Movie.find({}, 'name description release_year genre', (error, movies) => {
        if (error) console.error(error)

        res.send(movies);
      })
  })

  // fetch a single movie
  app.get('/movies/:id', (req, res) => {
    Movie.findById(req.params.id, 'name description release_year genre', (error, movie) => {
      if (error) console.error(error)

      res.send(movie);
    })
  })
}


Код controllers/users.js:

const User = require('../models/User');

const passportJWT = require('passport-jwt');
const jwt = require('jsonwebtoken');

const ExtractJwt = passportJWT.ExtractJwt;
const jwtOptions = {};
jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('jwt');
jwtOptions.secretOrKey = 'thisisthesecretkey';

module.exports.controller = app => {
  // register a user
  app.post('/users/register', (req, res) => {
    const newUser = new User({
      name: req.body.name,
      email: req.body.email,
      password: req.body.password,
    })

    User.createUser(newUser, (error, user) => {
      if (error) {
        res.status(422).json({
          message: 'Something went wrong. Please try again after some time'
        })
      }

      res.send({ user });
    })
  })

  // login user
  app.post('/users/login', (req, res) => {
    if (req.body.email && req.body.password) {
      const email = req.body.email,
        password = req.body.password;

      User.getUserByEmail(email, (err, user) => {
        if (!user) {
          res.status(404).json({ message: 'The user does not exist' })
        } else {
          User.comparePassword(password, user.password, (error, isMatch) => {
            if (error) throw error;

            if (isMatch) {
              const payload = { id: user.id };
              const token = jwt.sign(payload, jwtOptions.secretOrKey);
              res.json({ message: 'ok', token })
            } else {
              res.status(401).json({ message: 'The password is incorrect' })
            }
          })
        }
      })
    }
  })
}


Скрипт из компонента Home.vue, содержащий AJAX-запрос

<script>
import axios from 'axios';
import MovieCard from '@/components/MovieCard.vue';

export default {
  name: 'Home',
  components: {
    MovieCard,
  },
  data: () => ({
    movies: [],
  }),
  mounted() {
    this.fetchMovies();
  },
  methods: {
    async fetchMovies() {
      const token = window.localStorage.getItem('auth');

      return axios({
        method: 'get',
        url: 'http://localhost:8081/movies',
        headers: {
          Authorization: `JWT ${token}`,
          'Content-Type': 'application/json',
        },
      })
        .then((response) => {
          console.log(response);
        });

      // return axios.get('http://localhost:8081/movies')
      //   .then(({ data }) => {
      //     this.movies = data;
      //   })
      //   .catch((error) => {
      //     console.error(error);
      //   });
    },
  },
};
</script>


Пробовал разные методы решения этой проблемы, например, менял ExtractJWT.fromAuthHeaderWithScheme('jwt') на ExtractJWT.fromAuthHeaderWithScheme('bearer'), но это не помогло. Как исправить ошибку 401?
  • Вопрос задан
  • 22 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы