JSON Web Token авторизация для Sails.js

Рассматривая фреймворк Sails.js в качестве инструмента реинкарнации одного старого PHP-проекта я решил попутно посмотреть что есть из готовых модулей для реализации авторизации с применением JSON Web Token (JWT).
Так вот, на момент публикации статьи, готовые решения отсутствуют. Есть лишь небольшой ряд примеров по работе с JWT в Sails, абсолютно не готовых для использования в конечном продукте.

В итоге, на основе лучших идей из доступных примеров я написал собственную имплементацию JWT-авторизации для Sails.

Github: deliaz/sails-api-jwt


Несколько слов про архитектуру и доступные методы.

На данный момент готово:

  • Регистрация;
  • Авторизация;
  • Генерация и валидация JWT;
  • Получение информации о профиле;
  • Сброс пароля с отправкой ключа на email;
  • Изменение пароля (у пользователя с действующим JWT);
  • Блокировка после N-неудачных попыток авторизации.

Что предстоит сделать:

  • Шифрование токена сброса пароля;
  • Снятие блокировки с аккаунта спустя время;
  • Подтверждение регистрации с токеном-подтверждения.

Установка и запуск

Проект доступен в качестве NPM-модуля.
Установка:

npm i sails-api-jwt

После установки необходимо поменять секрет токена JWT_SECRET в файле api/config/env/development.js.

Запуск:

npm run start

или, если у вас установлен Sails глобально:

sails lift

JWT-авторизация

Все методы реализованы в контроллере UserController.

Методы, не требующие наличие токена:

/user/create
/user/login
/user/forgot
/user/reset_password

Методы, которым необходимо наличие JW-токена:

/user
/user/change_password 

При этом токен передается в качестве заголовка Authorization:

Authorization: Bearer <JWT...>

Описание методов

По ряду причин я не использую в данном модуле REST. Упрощенный доступ к методам ("shortcuts") также отключен (см. конфигурацию в файле api/config/blueprints.js).

POST /user/create

Создание нового пользователя. Пароль должен состоять из 6–24 символов с применением цифр и латиницы.

Запрос:

{
  "email": "email@example.com",
  "password": "abc123",
  "password_confirm": "abc123"
}

Ответ:

{
  "token": "<JWT>"
}

POST /user/login

Авторизация пользователя.
Важный момент: если в течении 2-х минут было 5 неудачных попыток авторизации, то аккаунт будет заблокирован. Изменить значения констант можно в файле api/services/UserManager.js.

Запрос:

{
  "email": "email@example.com",
  "password": "abc123"
}

Ответ:

{
  "token": "<JWT>"
}

GET /user

Возвращает информацию о текущем аккаунте. Необходима авторизация.

Запрос:
Параметры не требуются.

Ответ:

{
  "id": 1,
  "email": "email@example.com"
}

POST /user/change_password

Смена пароля. Пользователь должен быть авторизован.

Запрос:

{
  "email": "email@example.com",
  "password": "abc123", 
  "new_password": "xyz321",
  "new_password_confirm": "xyz321"
}

В ответ приходит новый JWT, старый токен более не считается валидным.
Ответ:

{
  "token": "<JWT>"
}

POST /user/forgot

Запуск процедуры восстановления пароля. Пользователю направляется email с ключем сброса.
В режиме разработке (dev-окружение) ключ выводится в консоль.

Запрос:

{
  "email": "email@example.com"
}

Ответ:

{
  "message": "Check your email"
}

POST /user/reset_password

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

Запрос:

{
  "email": "email@example.com",
  "reset_token": "<Password Reset Token>",
  "new_password": "xyz321",
  "new_password_confirm": "xyz321"
}

Ответ:

{
  "message": "Done"
}

HTTP-статусы

Все методы используют HTTP статус-код в качестве уведомления о результатах выполнения запроса.
Возможные значения:

  • 200 ok, запрос выполнен успешно;
  • 201 created, пользователь успешно создан;
  • 400 bad request, переданы неверные параметры;
  • 403 forbidden, аккаунт заблокирован;
  • 500 server error, ошибка на уровне сервера.

Особенности

  1. Пользователь считается авторизованным сразу после регистрации. Дополнительных манипуляция для получения токена не требуется.
  2. При успешном сбросе пароля методом /user/reset_password необходимо выполнить повторную авторизацию.

Тесты

Проект включает в себя E2E-тесты для API-методов. Текущее покрытие кода - 95%.
Репозиторий имеет интеграцию с сервисами Travis-CI и Coveralls.

Запуск тестов вручную и генерация отчета о покрытии:

npm run test

Присутствует конфигурация для ESLint.

Лицензия

Лицензия проекта – MIT.

За основу проекты был взят репозиторий swelham/sails-jwt-example (не имеет лицензии).