Мы запустили блог на «Хабре» совсем недавно, и в комментариях к первой же статье было много вопросов о том, когда и как мы планируем устранять проблему с логином на сервисах AliExpress. И сегодня я расскажу, что вообще пошло не так, как мы чинили баг(и), с чем уже удалось справиться, а что будет улучшено в будущем.
Введение: мультидоменная авторизация и при чём тут Intelligent Tracking Prevention
Как известно, сессионные секреты чаще всего хранятся в куках, а куки доступны в конкретном домене. При этом изначально все браузеры принимали куки, проставленные на сторонних сайтах, то есть не на том ресурсе, где пользователь находится прямо сейчас. С технической точки зрения это удобно: взял ajax-скрипт, дернул что-то с другого домена — и кука прочиталась/поставилась.
К сожалению, этот механизм стал основой активного слежения за пользователями веба, что не нравилось последним настолько, что был порожден целый класс плагинов к браузерам, которые предотвращали сбор данных сторонними трекерами.
Современные браузеры очень похожи по своим основным функциям, и на волне борьбы за privacy началось встраивание умных функций предотвращения слежения. Всё началось с попытки классификации сайтов на доверенные/недоверенные на основе истории посещений еще в 2017 году.
А закончилось полной блокировкой установки third-party cookies в дефолтных настройках в 2019-м. Причины введения таких правил описаны, например, тут.
Как всё это повлияло на разработчиков популярных сервисов
Массовая блокировка трекеров в первую очередь повлияла на рекламные возможности компаний по всему миру: им стало сложнее отслеживать активность пользователей для аналитики в целях таргетированной рекламы.
Но был и неприятный побочный эффект, который испытали на себе разработчики продуктов, которым функциональность third-party cookies была нужна совсем для другого. В их числе оказались и мы.
Как всё работало у нас
AliExpress.ru отличается от обычных интернет-магазинов тем, что это локализованная версия глобального AliExpress.com. В итоге русскоязычный сайт наследует/делит авторизацию от сайта в зоне .com, как и проект Tmall.
При этом флоу аутентификации устроен так: пользователь, пришедший на любой из сайтов, сначала проходит аутентификацию, а уже потом во всех доменах ему расставляются куки. Чтобы пользователю всего этого не было заметно, процесс проходит в фоне с помощью AJAX-запроса.
Данный способ вполне адекватен, и долгое время с ним не было проблем, но они начались по мере того, как популярные браузеры начали блокировать технологию трекинга с помощь пикселей. В итоге куки, проставляемые с помощью AJAX-запросов в домены, отличные от того, где находится пользователь, браузеры перестали сохранять. То есть сервер генерирует и возвращает куки, не зная, что браузер их удалил.
В итоге у пользователя работает сессия на том ресурсе, где он инициировал аутентификацию, а в двух других ее просто нет. Большая часть сервисов для русскоязычных пользователей находится в зоне .ru, и они в такой ситуации работают нормально. Но часто возникает необходимость обратиться к Tmall.ru или AliExpress.com — например, при обращении к нелокализованному сервису. И тут уже возникает ситуация, при которой залогиненный на AliExpress.ru пользователь оказывается разлогиненным в зоне .com.
Login loop
Описанная выше проблема на первый взгляд не выглядит очень уж страшно: ну попросит система пользователя авторизоваться еще раз, неудобства же на этом заканчиваются. Так бы оно и было, если бы у нас не была реализована локализация на уровне приложения. Грубо говоря, это означает, что, когда русскоязычный пользователь приходит сначала на AliExpress.com, сервис понимает: это клиент для AliExpress.ru, и редиректит его туда. Имено такой подход был реализован на главной — https://aliexpress.ru/com — и на основной странице логина — https://login.aliexpress.ru/com.
Если у пользователя был браузер, который блокирует куки, то получался замкнутый круг. Клиент приходил на aliexpress.com, его редиректило на aliexpress.ru, там он авторизовывался, попадал в личный кабинет в домене aliexpress.ru, а потом, например, пытался оставить отзыв через «оценку сделок», вызывая https://feedback.aliexpress.com.
Из-за отсутствия кук этот ресурс его не узнавал и отправлял заново логиниться на login.aliexpress.com, который по правилу локализации перенаправлял его в login.aliexpress.ru с параметрами запроса авторизации. Там сервер его уже знает: «русскоязычная» кука же сохранилась, — но из-за «подозрительной» попытки повторного логина просит подтвердить человеческое происхождение и решить капчу, а также производит стандартную простановку кук, как и при первоначальном логине. Затем по return url пользователя возращают на feedback.aliexpress.com, где снова проверяется сессия и из-за отсутствия cookie в домене aliexpress.com будет снова инциирован логин и всё повторяется снова.
Трудно придумать более раздражающего пользователя поведения сайта. И хотя проблема возникала не при покупке товаров, а при использовании сопутствующих фич вроде создания отзыва или проверки трека посылки, хорошего во всем этом было мало.
Как мы решали проблему
Первый шаг: мы отключили редирект login.aliexpress.com<->login.aliexpress.ru для локализации на уровне приложения. Таким образом мы дали возможность повторно авторизоваться и воспользоваться всеми сервисами. Данный шаг сам по себе не является решением основной проблемы авторизации, но исправляет ошибку полной недоступности сервисов из-за login loop. Тем самым мы смогли снять острую фазу проблемы для примерно 5% всех пользователей aliexpress.ru, попадавших в login loop.
На втором этапе мы решили саму проблему с дропающимися куками. Для исправления ситуации нам пришлось внепланово заняться изучением механизмов авторизации, которые изначально не входили в план локализации.
Контроль сессии изначально относится к уровню платформы глобальной Alibaba, и локализация этого сервиса не предполагалась поначалу (что и как мы сделали и будем делать в этом плане, описано в нашей предыдущей статье). В итоге authentication flow был доработан. Пришлось отказаться от silent-режима с помощью ajax-запросов в пользу редиректов, что потребовало определенного времени.
Почему чинили так долго
Самой большой проблемой было то, что механизмы контроля сессии не входили в план локализации и пришлось изучать проблему без возможности «поковырять» сам исходный код.
Для исправления необходимо было поправить не только authentication flow, но и все фронтовые приложения, которые вызывают аутентификацию. Так как исправлять пришлось не локализованные сервисы, то здесь потребовалось взаимодействие с коллегами из глобальной Alibaba, инженерная команда которой расположена в Китае.
При этом для платформы Alibaba эта ошибка в целом некритична, потому что в ней не используются мультидоменные приложения. Если проблема аффектит около 0,25% клиентов в целом, то ее трудно считать критичной. Это значит, внимание к ней не на высоком уровне и апдейты выкатываются не так быстро, как хотелось бы всем причастным к локализованной версии продукта.
Заключение: что мы будем делать дальше
Несмотря на то что основные проблемы уже решены, в бэклоге нашей инженерной команды еще достаточно задач. В нашем to-do:
Исправить все одностраничные приложения, которые не позволяют обновиться при авторизации. К сожалению, тут потребуется более глубокая переработка механизмов контроля сессии и передачи секретов.
Доделать все патчи для logout (да-да, на выходе есть такие же проблемы, но не в таком масштабе).
И вместо заключения немного статистики:
3d-party cookies отключены примерно у 25% клиентов AliExpress;
на текущий момент не более 4% логинов осуществляется через непропатченные точки входа, которые не ставят куки в других доменах;
90% сценариев таких логинов не предусматривают дальнейшего перехода из *.aliexpress.ru в *.aliexpress.com
На сегодня всё, спасибо за внимание! Буду рад ответить на вопросы в комментариях.
P. S. Валя, Егор, Георгий, Юра и jsoN – огромное вам спасибо за помощь в решении проблем!