На третий день настройки аутентификации для стартапа стало ясно: что-то идёт не так. Не в духе «пропустил точку с запятой», а скорее «выполнил каждый шаг из документации, а сброс пароля всё равно ведёт не туда, куда нужно».
В браузере было открыто двенадцать вкладок с документацией. Код примеров скопирован построчно. Даже просмотрено видео от человека, который явно уже проходил через нечто подобное.
Опыт внедрения аутентификации уже был — приходилось работать с 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 и видя этот пул пользователей, я чувствую тихую, глухую обиду. Как к соседу по квартире, который никогда не моет посуду и постоянно «одалживает» твои вещи.
Знакомое чувство.