Разбираемся с процессом авторизации в 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
и подключаем методыpassport
serializeUser
anddeserializeUser
. - Определяем маршрут, в котором будем использовать миддлвар
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()