Разбираемся с процессом авторизации в passport.js
Перевод статьи Understanding passport.js authentication flow
Passport.js - миддлвар для авторизации (позволяющий пользователям логиниться), который может быть полностью кастомизирован и отлично работает в связке с connect/express.
Он является довольно гибким в том смысле, что позволяет использовать разные стратегии авторизации (допустим через Twitter, или с помощью собственной базы данных - за счет установки отдельных модулей и их комбинирования), а также passport.js позволяет определить маршрут или вывод результата авторизации.
Стратегия Local Strategy позволяет пользователям авторизоваться, используя базу данных приложения. Для этих случаев есть несколько отличных примеров.
В этой статье, мы разберемся с процессом авторизации, а в следующей разберем несколько практических сценариев использования passportjs.
Основные моменты при использовании passport.js
Есть 3 момента при использовании passport.js:
- Импортируем модуль и вызываем методы
passport.initialize()иpassport.session()для миддлвары express. - Настраиваем для
passportхотя бы одну стратегиюStrategyи подключаем методыpassportserializeUseranddeserializeUser. - Определяем маршрут, в котором будем использовать миддлвар
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
passport.initializeмиддлвар вызывается на каждый запрос. Убеждается что сессия содержитpassport.user objec t, который может быть пустым.passport.sessionмиддлвар - часть стратегииPassport Strategy: загружает объект пользователяuserвreq.user, если сериализованный объект найден на сервере.passport.deserializeUserвызывается на каждый запрос из миддлвараpassport.session. Это позволяет нам подгружать дополнительную информацию пользователя при каждом запросе. Этот объект пользователяuserбудет прикреплен к запросу в видеreq.user, чтобы можно было получить к нему доступ при обработке запросов.Наша локальная стратегия
Local Strategyвызывается только при использовании маршрута который содержит миддлварpassport.authenticate.Только при авторизации вызывается
passport.serializeUserпозволяя нам определить какая информация пользователя будет записана в сессии.
Методы passport прикрепленные к запросу request
Ну и наконец обзор методов passport доступных внутри обработчиков запросов:
req.login()req.logout()req.isAuthenticated()req.isUnAuthenticated()