Сохранение JWT на стороне клиента - PullRequest
0 голосов
/ 21 мая 2019

Я использую PassportJS для реализации стратегии авторизации JWT в приложении NodeJS / Express.

Во всех руководствах токен JWT просто отсылается обратно по маршруту POST / login и вручную вставляется в заголовки запроса для демонстрации (см. Узнайте, как использовать JWT с аутентификацией по паспорту , Узнайте, как для обработки аутентификации с помощью Node с использованием Passport.js ), которая прекрасно работает в контексте API, но не веб-приложения, доступного из браузера.

Мой вопрос: как сохранить токен авторизации на стороне клиента, чтобы браузер отправлял его каждый раз в заголовках своих запросов?

Вот обзор моего кода (я удалил ненужные строки):

# users.js

router.post('/login', auth.optional, (req, res, next) => {

  return passport.authenticate('local', { session: false }, (err, passportUser, info) => {
    if (err) {
      res.render('/users/login');
    }

    if (passportUser) {
      const user = passportUser;
      user.token = passportUser.generateJWT();

      return res.json({ user: user.toAuthJSON() });
      // I want to set the auth header here
    }

    return res.status(400).info;
  })(req, res, next);
});

router.get('/me', auth.required, (req, res, next) => {
  res.render('me'); // Throws a 401 - No authorization token was found
});

При попытке доступа к / me выдается 401 - токен авторизации не найден ошибка, что имеет смысл, поскольку токен никогда не устанавливается. Но как это реализовать?

# промежуточного / auth.js

const getTokenFromHeaders = (req) => {
  ...
};

const auth = {
  required: jwt({
    secret: 'secret',
    userProperty: 'payload',
    getToken: getTokenFromHeaders
  }),
  optional: jwt({
    secret: 'secret',
    userProperty: 'payload',
    getToken: getTokenFromHeaders,
    credentialsRequired: false
  })
};

конфиг / passport.js

passport.use(new LocalStrategy({
  usernameField: 'email',
  passwordField: 'password'
}, (email, password, done) => {
  User.findOne({ email })
    .then((user) => {
      if (!user || !user.validatePassword(password)) {
        return done(null, false, { errors: { 'email or password': 'is invalid' } });
      }

      return done(null, user);
    }).catch(err => done(err));
}));

Большое спасибо за вашу помощь.

1 Ответ

1 голос
/ 21 мая 2019

Ваш бэкэнд должен установить его в виде файлов cookie HttpOnly и Secure в том же домене или поддомене, где находится ваш интерфейс.Затем в вашем веб-интерфейсе вам необходимо установить credentials: include для всех ваших запросов обратно на сервер, что означает, что ваш внешний интерфейс должен включать все файлы cookie, полученные с сервера, во все запросы обратно на сервер.Установка JWT в cookie-файл является предпочтительным способом хранения токенов доступа и наилучшим способом защиты от злонамеренных атак, поскольку cookie-файл не может быть прочитан никаким javascript-кодом, введенным на вашем сайте.См. Источник ниже.

Или, если по какой-либо причине у вас нет возможности установить JWT в cookie на вашем сервере, возможно, вы не контролируете его или используете стороннего поставщика аутентификации, такого какMicrosoft Active Directory как эмитент вашего токена.В этом случае вы можете пойти по гораздо менее идеальному маршруту и ​​установить JWT в локальном хранилище, которое очень подвержено краже, поскольку любой JavaScript, работающий на вашем сайте, имеет доступ к локальному хранилищу.

Источник: https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage

...