Тестирование двухфакторной аутентификации

Основные принципы

Двухфакторная аутентификация (2FA) является критическим элементом безопасности веб-приложений. При автоматизированном тестировании необходимо учитывать, что процесс аутентификации включает два последовательных шага: стандартный ввод учетных данных и подтверждение второго фактора, часто в виде кода, генерируемого приложением или отправляемого по SMS/Email.

Protractor позволяет реализовать тестирование 2FA через управление потоками ввода, ожидание динамически появляющихся элементов и интеграцию с внешними сервисами для получения одноразовых кодов.

Настройка окружения

Для работы с Protractor требуется конфигурационный файл protractor.conf.js. В нем задаются базовый URL приложения, браузерные возможности и стратегии ожидания элементов. Для тестирования 2FA рекомендуется включить:

capabilities: {
    browserName: 'chrome',
    chromeOptions: {
        args: ['--disable-infobars', '--start-maximized']
    }
},
allScriptsTimeout: 30000,
getPageTimeout: 30000

Ключевой момент: стандартные таймауты часто нужно увеличивать из-за задержек при отправке кода второго фактора.

Авторизация с 2FA

Основной поток теста включает два этапа:

  1. Ввод логина и пароля
let usernameField = element(by.id('username'));
let passwordField = element(by.id('password'));
let loginButton = element(by.id('login-button'));

await usernameField.sendKeys('testuser');
await passwordField.sendKeys('securePassword');
await loginButton.click();

Используется метод sendKeys для заполнения полей и click для перехода на шаг подтверждения второго фактора.

  1. Ввод кода второго фактора

Код может приходить через API, SMS или Email. Для интеграции с Protractor удобно использовать асинхронный запрос к сервису, который возвращает актуальный код:

const axios = require('axios');

async function get2FACode(userId) {
    let response = await axios.get(`https://api.testserver.com/2fa/${userId}`);
    return response.data.code;
}

let codeField = element(by.id('2fa-code'));
let submitButton = element(by.id('submit-2fa'));

let code = await get2FACode('testuser');
await codeField.sendKeys(code);
await submitButton.click();

Особенность: необходимо использовать await и методы Protractor для синхронизации с ожиданием элементов. Прямая работа без ожидания может приводить к ошибкам из-за асинхронной загрузки страницы.

Управление ожиданиями

В 2FA крайне важно корректно использовать ожидания (ExpectedConditions) для элементов:

const EC = protractor.ExpectedConditions;
let twoFAInput = element(by.id('2fa-code'));

await browser.wait(EC.visibilityOf(twoFAInput), 10000, 'Поле для ввода 2FA не появилось');
await twoFAInput.sendKeys(code);

ExpectedConditions позволяют избежать попыток взаимодействия с элементами, которые еще не загружены, что часто случается при задержках отправки кода.

Проверка успешной аутентификации

После ввода 2FA необходимо проверить успешный вход:

let dashboard = element(by.id('dashboard'));
await browser.wait(EC.visibilityOf(dashboard), 10000, 'Дашборд не загрузился');
expect(await dashboard.isDisplayed()).toBe(true);

Можно добавить проверку наличия уведомления об успешном входе или корректного отображения имени пользователя.

Обработка ошибок и неправильного кода

Тесты должны предусматривать сценарии с некорректным кодом 2FA. Это позволяет убедиться, что система корректно блокирует доступ и отображает ошибки:

await codeField.sendKeys('123456'); // неправильный код
await submitButton.click();

let errorMsg = element(by.css('.error-message'));
await browser.wait(EC.visibilityOf(errorMsg), 5000);
expect(await errorMsg.getText()).toContain('Неверный код');

Рекомендации по архитектуре тестов

  • Разделять шаги авторизации на отдельные функции: login(username, password) и submit2FA(code). Это облегчает повторное использование и поддержку тестов.
  • Использовать Page Object Model для инкапсуляции элементов и действий. Например, отдельный объект LoginPage с методами enterCredentials, enter2FACode и submit.
  • Интегрировать с сервисами, генерирующими коды 2FA, чтобы тесты оставались полностью автоматизированными.
  • Добавлять обработку таймаутов и ошибок сети, так как задержки доставки кода могут быть значительными.

Особенности тестирования через Protractor

Protractor работает поверх Selenium WebDriver, что позволяет управлять браузером и синхронизировать действия с Angular-приложениями. При тестировании 2FA важно:

  • Использовать browser.waitForAngularEnabled(false) для страниц, не зависящих от Angular (например, внешние сервисы отправки кода).
  • Применять асинхронные функции для последовательного выполнения шагов.
  • Не хранить реальные учетные данные и коды 2FA в тестах — использовать тестовые учетные записи и изолированные сервисы для получения кодов.

Автоматизация через CI/CD

Тестирование 2FA интегрируется в пайплайны CI/CD, но требует:

  • Возможности получать коды через API без ручного вмешательства.
  • Настройки браузеров в headless-режиме для ускорения выполнения тестов.
  • Логирования шагов и ошибок для отладки при сбоях аутентификации.

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