Учимся работать с аутентификацией в Node используя Passport.js

Dmitry Kulbeda
NOP::Nuances of Programming
4 min readJul 2, 2018

Перевод статьи Antonio Erdeljac: Learn how to handle authentication with Node using Passport.js

Фотография Oskar Yildiz на Unsplash

В этой статье вы узнаете, как разработать аутентификацию для вашего Node-сервера используя Passport.js. Эта статья не включает в себя фронт-энд аутентификацию. Используйте её для настройки бэк-энда вашей аутентификации (сгенерировать токен для каждого пользователя и защитить маршруты).

Также помните, что если вы застряли на каком-либо из этапов, вы можете использовать этот GitHub-репозиторий.

В этой статье я научу вас следующему:

  • Работать с защищёнными маршрутами
  • Работать с JWT (JSON Web Token) токенами
  • Обработка неавторизованных запросов
  • Создание базовой API
  • Создание моделей и схем

Вступление

Что такое Passport.js?

Паспорт — это промежуточное программное обеспечение для Node.js. Ввиду своей невероятной гибкости и модульности, Паспорт может быть закинут в любое веб-приложение на основе Express. Полный набор стратегий поддерживает аутентификацию с помощью имени пользователя и пароля от аккаунтов Facebook, Twitter, и так далее. Больше о Паспорте вы можете прочитать здесь.

Обучение

Создаём с нуля свой node-сервер

Создаём новую директорию с файлом “app.js” внутри:

Теперь установим nodemon для более лёгкой разработки.

А теперь с помощью этого запустим своё приложение “app.js”.

$ nodemon app.js
Ожидаемый результат после введения команды выше

Создание модели пользователя

Создайте новую папку под названием «models» и создайте файл «Users.js» внутри этой папки. Здесь мы определим нашу «UsersSchema». Мы собираемся использовать JWT и Crypt для генерации has и salt из полученной строки password. В дальнейшем это будит использоваться для валидации пользователя.

Теперь у вас должна быть такая структура

Теперь добавим только созданную нами модель в “app.js”.

Добавьте следующую строку в ваш файл “app.js” после настройки Mongoose:

require('./models/Users');

Настройка паспорта

Создайте новую папку с названием “config” и файлом “passport.js” внутри:

В этом файле мы используем метод validatePassword, который мы описали в User model. В зависимости от результата, мы возвращаем разный вывод из Паспортной LocalStrategy.

Ваша структура должна выглядеть так

Теперь подключим “passport.js” к нашему файлу “app.js”. Добавьте следующую строчку ниже всех models:

require('./config/passport');
Требование паспорта должно быть под всеми моделями

Маршруты и опции аутентификации

Создайте новую папку с названием “routes” и файлом “auth.js” внутри.

В этом файле мы использем функцию getTokenFromHeaders для получения JWT токена, который будет отправлен с клиентской стороны в заголовки запроса. Мы также создаём auth-объект c optional и required свойствами. Мы используем это позже в наших маршрутах.

В той же папке “routes” создайте файл “index.js”:

Теперь нам нужна папка “api” внутри папки “routes” с ещё одним файлом “index.js” внутри.

Ваша структура должна выглядеть так

Теперь давайте создадим файл “users.js”, которым необходим нам в “api/index.js”.

Сперва, мы собираемся создать маршрут необязательной аутентификации ‘/’, который будет использован для создания новой модели (регистрации).

router.post('/', auth.optional, (req, res, next) ...

После этого мы создаём другой маршрут необязательной аутентификации ‘/login’. Этот будет использован для активации конфигурации нашего паспорта и подтверждения полученного пароля с помощью электронной почты.

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

Наконец, мы создадим маршрут обязательной аутентификации, который будет использован для возврата текущего зарегистрированного пользователя. Только вошедшие пользователи (пользователи, которые успешно отправили свой токен через заголовки запроса) имеют доступ к этому маршруту.

router.get('/current', auth.required, (req, res, next) ...
Ваша структура должна выглядеть так

Теперь добавим папку наших “routes” в “app.js”. Добавьте следующую строчку ниже require нашего паспорта:

app.use(require('./routes'));

Тестирование маршрутов

Я буду использовать Postman для отсылки запросов на наш сервер.

Наш сервер принимает следующую форму:

{
"user": {
"email": String,
"password": String
}
}

Создание POST-запроса для создания пользователя

Испытываемая форма:

Ответ:

{
"user": {
"_id": "5b0f38772c46910f16a058c5",
"email": "erdeljac.antonio@gmail.com",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImVyZGVsamFjLmFudG9uaW9AZ21haWwuY29tIiwiaWQiOiI1YjBmMzg3NzJjNDY5MTBmMTZhMDU4YzUiLCJleHAiOjE1MzI5MDgxNTEsImlhdCI6MTUyNzcyNDE1MX0.4TWc1TzY6zToHx_O1Dl2I9Hf9krFTqPkNLHI5U9rn8c"
}
}

Теперь мы используем этот токен и добавим его в наши “Headers” в Postman конфигурации.

А теперь давайте протестируем наш маршрут только аутентификации.

Создаём GET-запрос для возвращения текущего зашедшего пользователя

Запрос URL:

GET http://localhost:8000/api/users/current

Ответ:

{
"user": {
"_id": "5b0f38772c46910f16a058c5",
"email": "erdeljac.antonio@gmail.com",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImVyZGVsamFjLmFudG9uaW9AZ21haWwuY29tIiwiaWQiOiI1YjBmMzg3NzJjNDY5MTBmMTZhMDU4YzUiLCJleHAiOjE1MzI5MDgzMTgsImlhdCI6MTUyNzcyNDMxOH0.5UnA2mpS-_puPwwxZEb4VxRGFHX6qJ_Fn3pytgGaJT0"
}
}

Давайте попробуем сделать это без токена в “Headers”.

Ответ:

--

--