OAuth авторизация в Cypress

07 апр. 2020

Использование в end-to-end тестах сторонних сервисов, которые мы не контролируем, считается антипаттерном: сервисы могут ограничивать количество запросов или изменять UI — это может повлиять на выполнение тестов в нашем приложении.

Поэтому, если в приложение, которое вы покрываете тестами, авторизация происходит на отдельном домене (например, через Гугл), вместо заполнения UI формы авторизации, надо запросить авторизационный токен через API сервиса авторизации.

Для авторизации через OAuth можно воспользоваться методом Resource Owner Password Grant: отправить POST запрос с данными учётной записи (credentials) на endpoint API авторизации для получения токена, а затем добавить токен в headers HTTP запросов.

URL для получения токена ищите в документации фреймворка авторизации, который используете. Например, в IdentityServer надо отправить POST запрос на example.com/connect/token.

Данный тип авторизации не рекомендуется использовать для сторонних приложений, потому что он подразумевает хранение и использование данных учётной записи. Используйте его только, если уверены в безопасности реализации.

Проверяем метод через Postman

Прежде чем перейти к написанию кода, надо проверить правильность сформированного POST запроса, и приходит ли токен в ответе от сервера. Удобнее всего это сделать через Postman.

Выбираем тип запроса POST, вводим URL для получения токена, и добавляем необходимые свойства запроса:

  • grant_type — способ авторизации, в этом методе используется ‘password’,
  • username — логин учётной записи,
  • password — пароль учётной записи,
  • client_id — название клиента для авторизации вашего приложения, добавляется в панели управления OAuth,
  • client_secret — пароль клиента для авторизации вашего приложения,
  • scope — список ресурсов, к которым вы хотите получить доступ.

OAuth postman test

Если в ответе от сервера возвращается access_token, значит мы используем правильные данные и отправляем запрос по нужному URL. Этот токен надо добавить в headers ваших запросов к API.

Создаём команду в Cypress

Теперь добавим новую команду для Cypress в cypress/support/commands.js:

Cypress.Commands.add('login', () => {
  Cypress.log({
    name: 'loginBySingleSignOn',
  });
  // Авторизуемся
  cy.request({
    method: 'POST',
    // Endpoint авторизации
    url: 'https://example.ru/connect/token',
    form: true,
    body: {
      // Тестовая учётка
      username: 'username',
      password: 'password',
      // Авторизуемся через grant type "password"
      grant_type: 'password',
      // Заправшиваем доступ ко всем необходимым скоупам
      scope: 'openid profile email api',
      client_id: 'spa_name',
      client_secret: 'password',
    },
  }).then((res) => {
    cy.server({
      // Добавляем в заголовок с токеном в каждый запрос
      // Не забудьте отключить автоматическую авторизацию
      // в приложение, если она у вас включена.
      // Иначе она будет перезаписывать ваш токен
      onAnyRequest: (route, proxy) => {
        proxy.xhr.setRequestHeader('Authorization', 'Bearer ' + res.body.access_token);
      },
    });

    // Переходим на главную страницу приложения
    cy.visit('<http://localhost:4200>');
  });
});

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

Как применять

Далее в каждом тестовом сценарии выполняем авторизацию перед каждым тест-кейсом:

Теперь запустите тест. Авторизация должна работать:

Cypress authorization

Богдан Звягинцев

Спасибо за внимание! Если вы нашли ошибку или у вас есть дополнения, напишите мне в Телеграм.

© Богдан Звягинцев, 2022