Используйте Ally с защитой API и SPA

AdonisJS — это версия Laravel для Node.js. В отличие от других фреймворков, цель AdonisJS — упростить разработку бэкенда без хлопот, с которыми сталкиваются разработчики.

AdonisJS, как и Laravel, является фреймворком MVC (и дружественным к Typescript), а это означает, что вам не придется бороться с принятием шаблона проектирования. Конечно, вы можете настроить/добавить пространства имен.

Основная команда и члены сообщества создали множество пакетов, чтобы добавить несколько функций в структуру. Это список всех пакетов.

Один из таких пакетов называется Ally и предлагает возможность аутентификации пользователей через социальные сети и прямо из коробки поддерживает Github, Google, Twitter, Facebook, Discord, Spotify и LinkedIn.

Использование Ally в MAP (многостраничном приложении) безболезненно. Однако, когда дело доходит до SPA (одностраничное приложение), все становится сложнее. В этой статье мы увидим, как выполнять социальную аутентификацию при использовании SPA без сеанса.

Вместо установки пакетов в вашем SPA, которые будут обрабатывать социальную аутентификацию, мы будем использовать наше приложение AdonisJS в качестве единого источника достоверной информации для обслуживания URL-адресов и аутентификации пользователей.

Мы начнем с создания нового проекта AdonisJS. Для этого выполните следующую команду:

npm init adonis-ts-app@latest ally-spa

Когда дело доходит до вопроса о структуре проекта, выберите api.

Теперь мы настроим Элли.

npm i @adonisjs/ally

После установки нам нужно настроить пакет, сделать это можно всего одной командой:

node ace configure @adonisjs/ally

Приведенная выше команда будет:

  • Создать файл контракта contracts/ally.ts
  • Создайте файл конфигурации config/ally.ts
  • Обновить .envи .env.example файлы
  • Обновить файл tsconfig.json с типами пакетов
  • И, наконец, обновите файл .adonisrc.json с именем пакета в списке провайдера.

Вы также можете проверить переменные среды, требуемые драйверами пакета. В нашем примере мы будем использовать Google. Вы можете проверить Руководство Ally, чтобы узнать, как использовать другие драйверы с необходимой конфигурацией.

Откройте env.ts и добавьте следующий код:

Теперь откройте файл config/ally.ts и добавьте свой идентификатор клиента и секрет клиента. Чтобы получить свой идентификатор и секрет, вам необходимо настроить приложение Google OAuth 2.0 в консоли разработчика Google и создать учетные данные для клиента OAuth, используя учетную запись Google.

После создания приложения вам нужно будет создать учетные данные. На странице Credentials нажмите кнопку CREATE CREDENTIALS и выберите идентификатор клиента OAuth. Выберите Веб-приложение в качестве типа приложения. Выберите имя для вашего приложения. Затем вам нужно добавить URI для Authorised JavaScript origins. Это ДОЛЖЕН быть домен вашего SPA, в моем случае это будет http://localhost:9000. Наконец, вы должны добавить еще один URI для перенаправления. В Authorised redirect URIs добавьте URL-адрес, например: http://localhost:9000/auth/google (это зависит от вашего домена SPA и порта, я использую localhost, чтобы проверить, все ли работает).

Внутри config/ally.ts добавьте тот же URL-адрес перенаправления:

Используя приведенную выше конфигурацию Google, наше приложение AdonisJS теперь может генерировать URL-адрес перенаправления, который можно отправить в наш SPA.

Откройте start/routes.ts и добавьте следующий код:

Мы используем общий маршрут (используя общий параметр :provider), чтобы мы могли получить URL-адрес перенаправления для каждого настроенного драйвера. Если пользователь уже вошел в систему, мы отклоним запрос, ответив с кодом состояния = 406 (неприемлемо). В противном случае мы отправляем URL-адрес перенаправления в наш SPA.

Мы используем метод stateless, потому что мы не используем проверку CSRF.

Если вы используете Vue в качестве внешнего интерфейса, вы можете отправить запрос по указанному выше маршруту, используя axios или fetch API внутри обратного вызова хука onMounted, получить URL-адрес и добавить его к компоненту кнопки.

Теперь, когда у нас есть URL-адрес перенаправления, мы можем получить к нему доступ из SPA. Нажмите на нее, вам будет предложена форма согласия, где вы можете выбрать свою учетную запись Google. После выбора учетной записи вы будете перенаправлены на предоставленный URL-адрес обратного вызова (в моем случае это http://localhost:9000/auth/google).

Поставщик Google добавит строку запроса к нашему URL-адресу перенаправления. Мы отправим запрос на сервер с этими дополнительными данными, чтобы Ally могла аутентифицировать пользователей.

Ниже приведен код обработчика маршрута обратного вызова.

Как видите, мы используем непрозрачный токен доступа (OAT) от AdonisJS (помните, что это SPA, мы не используем сеансы) для авторизации последующих запросов. Токены провайдеров (от Google, Twitter и т. д.) используются для выполнения других операций в провайдерах, например: получение всех пользовательских репозиториев с GitHub.

В заключительной части нам нужно авторизовать последующие запросы. Мы создадим новое промежуточное ПО для получения непрозрачного токена доступа из файлов cookie и добавления его к заголовку каждого запроса.

node ace make:middleware SetAuthorizationHeader

Откройте App/Middleware/SetAuthorizationHeader.ts и добавьте следующее содержимое:

Наконец, вам нужно зарегистрировать промежуточное ПО в глобальном массиве промежуточного ПО внутри start/kernel.ts.

Теперь вы можете добавить промежуточное ПО Auth к маршруту, и оно проверит токен и предоставит доступ или откажет, если срок его действия истек. И вуаля, мы закончили!