Dmitry Vdovichenko

Разбираемся с процессом авторизации в passport.js

Перевод статьи Understanding passport.js authentication flow

Passport.js - миддлвар для авторизации (позволяющий пользователям логиниться), который может быть полностью кастомизирован и отлично работает в связке с connect/express.

Он является довольно гибким в том смысле, что позволяет использовать разные стратегии авторизации (допустим через Twitter, или с помощью собственной базы данных - за счет установки отдельных модулей и их комбинирования), а также passport.js позволяет определить маршрут или вывод результата авторизации.

Стратегия Local Strategy позволяет пользователям авторизоваться, используя базу данных приложения. Для этих случаев есть несколько отличных примеров.

В этой статье, мы разберемся с процессом авторизации, а в следующей разберем несколько практических сценариев использования passportjs.

Основные моменты при использовании passport.js

Есть 3 момента при использовании passport.js:

  1. Импортируем модуль и вызываем методы passport.initialize() и passport.session() для миддлвары express.
  2. Настраиваем для passport хотя бы одну стратегию Strategy и подключаем методы passport serializeUser and deserializeUser.
  3. Определяем маршрут, в котором будем использовать миддлвар passport.authenticate непосредственно для авторизации пользователя.

Примеры в документации достаточно ясно показывают использование этих методов. Поэтому,подробнее здесь мы их не рассматриваем.

Процесс запроса на авторизацию

Итак, если мы верно настроили passportjs, согласно примеру выше, то при попытке пользователя авторизоваться по маршруту /login, произойдет следующее:

  • Когда пользователь отправит данные формы авторизации, POST запрос к маршруту /login вызовет выполнение мидлвар passport.authenticate, который мы подключили.
  • Поскольку миддлвар авторизации для этого маршрута настроен на использование стратегии LocalStrategy, passport вызовет нашу реализацию LocalStrategy.
  • Passport возьмет из запроса req.body.username и req.body.password и передаст их нашей функции проверки авторизации в LocalStrategy.
  • Теперь займемся своими делами: загрузим данные пользователя из базы данных и проверим совпадают ли пароли.

В случае если при взаимодействии с базой данных сработает ошибка, нам нужно передать ее методу done(err).

Когда мы не можем найти пользователя или пароли не совпали, мы вызываем done(null, false).

Если же все прошло хорошо, и мы хотим залогинить пользователя, вызываем done(null, user).

Вызов done позволит последовательности авторизации перепрыгнуть обратно в passport.authenticate. Передаются ошибка error, user и объект с дополнительной информацией (если он был определен).

Если объект user был передан, миддлвар вызовет req.login (метод passport, добавленный к запросу request).

Это приведет к вызову метода passport.serializeUser, который мы определили ранее.

Этот метод имеет доступ к объекту user, который мы передали в миддлвар.

Его работа заключается в том, чтобы определить, какие данные объекта user должны быть записаны в сессии session.

Результат выполнения метода serializeUser прикрепляется к сессии:

req.session.passport.user = { // our serialised user object // }.

Результат также прикреплен к запросу: req.user.

Когда все это выполнено, вызывается наш обработчик запросов requestHandler. В данном примере поьзователь будет перенаправлен на стартовую страницу.

Последовательность последующих запросов авторизации

При последующих запросах, произойдет следующее:

  • Express загрузит данные сессии и прикрепит их к запросу req. Так как passport записал выбранные данные пользователя в сессию, сериализованный объект user можно будет найти в req.session.passport.user.

  • Основной миддлвар passport, который мы настроили (passport.initialize) будет вызван при запросе, он найдет passport.user прикрепленный к сессии. Если он отсутствует (пользователь еще не авторизовался), то будет создан в следующем виде: req.passport.user = {}.

  • Затем, будет вызван passport.session. Этот миддлвар - часть стратегии Passport Strategy, вызываемой при каждом запросе. Если он найдет сериализованный объект пользователя user в сессии, он решит, что запрос request авторизован.

  • Миддлвар passport.session вызовет passport.deserializeUser, который мы добавили ранее. Тем самым, прикрепляя загруженный объект user к запросу в виде req.user.

Итого: все методы и мидллвары passport

  1. passport.initialize миддлвар вызывается на каждый запрос. Убеждается что сессия содержит passport.user objec t, который может быть пустым.

  2. passport.session миддлвар - часть стратегии Passport Strategy: загружает объект пользователя user в req.user , если сериализованный объект найден на сервере.

  3. passport.deserializeUser вызывается на каждый запрос из миддлвара passport.session. Это позволяет нам подгружать дополнительную информацию пользователя при каждом запросе. Этот объект пользователя user будет прикреплен к запросу в виде req.user, чтобы можно было получить к нему доступ при обработке запросов.

  4. Наша локальная стратегия Local Strategy вызывается только при использовании маршрута который содержит миддлвар passport.authenticate.

  5. Только при авторизации вызывается passport.serializeUser позволяя нам определить какая информация пользователя будет записана в сессии.

Методы passport прикрепленные к запросу request

Ну и наконец обзор методов passport доступных внутри обработчиков запросов:

  • req.login()
  • req.logout()
  • req.isAuthenticated()
  • req.isUnAuthenticated()