На третий день настройки аутентификации для стартапа стало ясно: что-то идёт не так. Не в духе «пропустил точку с запятой», а скорее «выполнил каждый шаг из документации, а сброс пароля всё равно ведёт не туда, куда нужно».

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

Опыт внедрения аутентификации уже был — приходилось работать с Auth0, укрощать Firebase Auth и даже писать собственную систему на JWT, которой не гордишься, но которая работала. Поэтому когда команда стартапа склонилась к Cognito («он уже часть экосистемы AWS, и первые 50 000 активных пользователей в месяц — бесплатно»), казалось: что может пойти не так?

Как оказалось — почти всё.

Документация написана сразу для пяти разных читателей

Чтение документации Cognito ощущается так, будто кто-то взял три разных руководства, смешал их в блендере и добавил щепотку устаревших ответов со Stack Overflow для аромата.

AWS пытается одновременно обслужить слишком много аудиторий. Есть архитектор из энтерпрайза, которому нужно понимать протоколы идентификации на низком уровне. Есть фронтенд-разработчик, которому нужна просто форма логина. Есть мобильный разработчик, которому нужны нативные SDK. Документация пытается быть полезной всем сразу — и в итоге не годится ни для кого конкретно.

Поиск по запросу «Cognito custom attribute validation» приводит на страницу, которая начинается с абзаца о схемах каталогов, предполагающего, что читатель уже прочитал четыре другие страницы, о существовании которых он даже не знал. Никакого чёткого линейного пути — просто паутина гиперссылок и надежда на удачу.

А примеры кода — это отдельная история. Половина написана для старого JavaScript SDK. Некоторые ссылаются на Amplify v1 API. Другие используют «сырой» AWS SDK. Документация не всегда чётко указывает, о какой версии идёт речь, так что приходится играть в детектива с импортами.

День, когда Amplify v6 предал доверие

Раз уж речь зашла о версиях — стоит рассказать про ситуацию с JavaScript-библиотекой, которая застала врасплох по-настоящему.

На старте проекта Amplify была на версии 5. Флоу аутентификации был написан, протестирован, закоммичен — команда перешла к другим фичам. Спустя несколько недель, при возвращении для исправления бага, в консоли обнаружились предупреждения об устаревании. Ничего страшного, подумалось тогда — просто нужно обновиться до последней версии.

Amplify v6 изменил не пару сигнатур методов — он фундаментально переработал сам способ взаимодействия с Cognito. Функции, вокруг которых были построены целые UI-флоу, исчезли. Заменены. Испарились. Гайд по миграции формально существовал, но больше напоминал карту сокровищ с half пропущенными ориентирами.

Код пришлось не рефакторить, а переписать заново. Логика аутентификации, прекрасно работавшая в продакшене, требовала полной пересборки — потому что мейнтейнеры библиотеки решили, что старый API больше не является благословенным путём. Это не апгрейд. Это захват заложников.

Локальная разработка — отдельный вид боли

Забавный факт про Cognito: это облачный сервис. Да, неожиданно. Но на практике это означает, что нельзя просто поднять локальный инстанс и протестировать флоу аутентификации офлайн. Запросы всегда идут к реальным эндпоинтам AWS.

Существуют инструменты вроде плагина serverless-offline и локальных эмуляторов Cognito, которые пытаются закрыть этот разрыв. Но это community-проекты с разным уровнем поддержки и точности воспроизведения. Официальная позиция AWS сводится к «тестируйте против облака» — отличный совет, если вы не в самолёте, у вас не барахлит интернет и вы не хотите быстрых циклов итерации без ожидания сетевых round-trip'ов.

Немало времени ушло на настройку локального мока, который не совсем соответствовал реальному поведению сервиса — из-за чего баги проскальзывали локально и всплывали уже на staging. Весь смысл локальной разработки — ловить проблемы на раннем этапе, а Cognito активно этому противодействует.

Хотите кастомизацию? Максимум — логотип

Это задело особенно сильно.

Хостируемый UI от Cognito функционален. Он есть. По большей части работает. Но если нужно, чтобы он выглядел как ваш бренд, а не как сервис AWS в костюме, придётся несладко.

Логотип поменять можно. Немного CSS через консоль подкрутить — тоже. Но макет, структуру, общее ощущение? Это дом AWS, а вы всего лишь снимаете в нём комнату. Если нужно что-то за пределами базовой кастомизации, совет от сообщества обычно один: «постройте собственный UI на базе SDK». Что ж, логично. Но тогда возникает вопрос — что именно экономит хостируемый UI?

Настройка email-only аутентификации, сломавшая дух

Был момент, когда хотелось выбросить ноутбук в окно.

Приложению требовалась только аутентификация по email. Никаких username. Пользователь регистрируется по email, подтверждает его, задаёт пароль — готово. Простая концепция, казалось бы.

В настройках пула пользователей Cognito был выбран email в качестве идентификатора для входа. Настроены маппинги атрибутов. Создан флоу регистрации. Всё выглядело нормально, пока не выяснилось, что Cognito трактует «email» по-разному в зависимости от того, является ли он core-атрибутом, алиасом или кастомным атрибутом — а опции конфигурации разбросаны по нескольким экранам консоли, с взаимозависимостями, которые нигде толком не объяснены.

В начальной настройке была допущена ошибка. Небольшая. Что-то было сконфигурировано как кастомный атрибут, хотя должно было быть стандартным. Не беда, подумалось — просто нужно поменять.

Поменять это нельзя.

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

Для продакшн-приложения с активными пользователями вариант «просто удалить» реальным не является. Так что приходится писать скрипты миграции пользователей, обрабатывать сброс паролей в новом пуле и извиняться перед пользователями за неудобства. И всё это из-за того, что выпадающий список в консоли оказался чуть более двусмысленным, чем следовало.

Что из этого действительно вынесено

Просто жаловаться — это легко. Но важно честно сказать, чему научил этот опыт, потому что за фразой «Cognito плохой» скрывается кое-что более полезное.

Аутентификация — не то место, где стоит срезать углы. Аргумент «оно уже в экосистеме» соблазнителен, но близость к экосистеме не имеет значения, если инструмент делает несчастным при каждом обращении к нему. Ценник бесплатного тарифа выглядит привлекательно, пока не посчитать инженерные часы, потраченные на борьбу с документацией и переписывание кода из-за ломающих изменений API.

В следующий раз выбор инструмента будет опираться в первую очередь на developer experience, а не на удобство интеграции с сервисами AWS. Время, потерянное на отладку проблем с Cognito, могло бы окупить несколько лет платного auth-провайдера. И релизы выходили бы быстрее, а холодной пиццы в полночь съедалось бы меньше.

Тем, кто сейчас оценивает Cognito для своего проекта, никаких прямых указаний давать не стоит. Но один совет всё же уместен: сначала соберите небольшой proof of concept. Что-то нетривиальное. С кастомными атрибутами, верификацией email и флоу сброса пароля. Оцените ощущения. Засеките время. Посчитайте, сколько вкладок с документацией открыто к концу процесса.

Если их больше двадцати — возможно, стоит пересмотреть решение.

Cognito до сих пор используется в этом проекте, кстати. Слишком далеко зашли, чтобы вырывать его сейчас. Но каждый раз, открывая консоль AWS и видя этот пул пользователей, я чувствую тихую, глухую обиду. Как к соседу по квартире, который никогда не моет посуду и постоянно «одалживает» твои вещи.

Знакомое чувство.