Как стать автором
Обновить

Авторизация через VK: что под капотом и как это тестировать

Уровень сложностиСредний
Время на прочтение10 мин
Количество просмотров1.3K

Авторизация в приложениях через сторонние сервисы уже давно стала привычной. Это и правда удобно. Не нужно запоминать, как именно ты вписал свой юзернейм — Va$ya или Vassssya? — и какой пароль выбрал — 123 или 321? Нажимаешь волшебную кнопку «Войти с помощью….» и попадаешь в личный кабинет. И раз эта фича появилась, значит, это кому-нибудь нужно (и кто-то это тестирует :)

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

Авторизация через VK: что под капотом?

Теория тестирования сообщает нам, что прежде чем что-то тестировать, нужно определиться с требованиями. Дополним от себя: прежде чем что-то тестировать, нужно понять, как именно оно работает.

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

Нажимаем кнопку VK на странице авторизации
Нажимаем кнопку VK на странице авторизации
Нажимаем кнопку VK на странице авторизации
Если мы уже авторизованы внутри VK, то нажимаем «Продолжить как…» . Если мы не авторизованы, на этой странице необходимо авторизоваться
Попадаем на главную страницу игры
Попадаем на главную страницу игры

Вот что в это время происходит внутри:

  • Уходит запрос на сервер VK

  • Сервер VK присылает нужные токены и значение VK_id пользователя

  • Отправляем эти данные на сервер «Битвы покемонов» 

  • Проверяем в базе данных игры, кому принадлежит этот VK_id

  • Присылаем в ответ session_id и сохраняем в его куки браузера

  • Авторизация успешно завершена

Рассмотрим этот алгоритм подробнее ↓

Первый шаг

Мы нажимаем кнопку VK на странице авторизации сайта покемонов. Важный момент: мы используем VK ID, предварительно зайдя в свой профиль VK в этом браузере.

Сначала происходит переход на один из поддоменов VK — id.vk.com. В квери-параметрах адреса уже содержится некоторая информация: 

  • UUID — идентификатор запроса на авторизацию

  • redirect_uri — конечная точка всего процесса: адрес, на который VK должен отправить ответ после успешной авторизации

  • app_id — идентификатор приложения. Он есть у всех приложений, к которым подключён вход через VK ID. По нему VK понимает, из какого именно мобильного или веб-приложения приходит запрос.

  • response_type — тот тип токена, который мы получим, после того как бэкенд VK обработает запрос на авторизацию. В данном случае это так называемый silent token.

Silent token используется, когда системе нужно выполнить операции без участия пользователя. Например, для записи статистики, обновления данных или доступа к API в автоматическом режиме с минимальным вмешательством человека.

Почти как в поликлинике — мы показываем серверу VK «направление»: кто именно пришёл (UUID), от какого терапевта (app_id), какую процедуру нужно провести (выдать silent token) и в какой кабинет направить дальше (redirect_uri).

Один запрос отправляется на поддомен login.vk.com. В боди содержится UUID — тот самый идентификатор запроса на авторизацию и app_id — идентификатор приложения.
Один запрос отправляется на поддомен login.vk.com. В боди содержится UUID — тот самый идентификатор запроса на авторизацию и app_id — идентификатор приложения.

Самое интересное, конечно, происходит на бэкенде.

Запрос уходит на login.vk.com
Запрос уходит на login.vk.com
Передаем свои UUID и app_id
Передаем свои UUID и app_id

В ответ приходит нужный нам silent token и access token.

Возвращается access token, silent token и ID профиля пользователя внутри VK
Возвращается access token, silent token и ID профиля пользователя внутри VK

Access token — аналог пропуска на стратегический объект. Вместе с ним наше приложение получает право запросить часть данных пользователя — имя, фамилию, телефон, фотографию профиля. В нашей реализации «Битвы покемонов» мы получаем только ID пользователя в соцсети VK. Он понадобится для поиска нашего пользователя уже внутри «Битвы покемонов».  

Параллельно с этими запросами на api.vk.com отправляется так называемый anonymous token

Анонимный токен нужен для стабильной работы всей системы и бесшовного процесса авторизации через VK ID. Называется анонимным, поскольку генерируется без запроса логина-пароля и выдается даже неавторизованным пользователям. Так что даже если бы мы не зашли предварительно в свой профиль VK, система все равно присвоила бы anonymous token на этом этапе: с его помощью мы смогли бы продолжить вход в «Битву покемонов» после авторизации в VK и не заблудились бы в редиректах.

Запрос уходит на api.vk.com 
Запрос уходит на api.vk.com 
Пользователю автоматически присваивается анонимный токен 
Пользователю автоматически присваивается анонимный токен 

В ответ на анонимный токен сервер присылает параметр «ключ» — key. Он понадобится серверу для подтверждения подлинности запросов в будущем, особенно если авторизация произойдет не сразу. Мы можем отвлечься на TikTok с котиками, сходить налить себе чай, встретить курьера — в это время key будет охранять наш процесс авторизации. 

В ответе присылается key и указывается время ожидания следующих событий
В ответе присылается key и указывается время ожидания следующих событий

Как это работает?

Обратим внимание на поле wait: 25. Оно означает, что после получения ответа от сервера клиент будет каждые 25 секунд отправлять новый запрос до тех пор, пока пользователь не нажмет кнопку «Продолжить как…». Таким образом, если пользователь бездействует, клиент и сервер все равно будут поддерживать связь друг с другом, чтобы не пришлось начинать авторизацию заново.

Этот механизм называется Long Polling.

Long Polling означает, что наше приложение отправляет запрос к серверу VK и ожидает ответа — в нашем случае до 25 секунд. Если в течение 25 секунд на сервере произойдет ожидаемое событие, сервер сразу отправит ответ. Если за 25 секунд ничего не произойдет, сервер вернёт пустой ответ, и приложение само должно снова отправить запрос. Так мы мгновенно узнаём об изменениях в системе, нет необходимости отправлять запросы каждую секунду — а значит, экономится трафик и снижается нагрузка на сервер. 

Ключ, конечно, действует не бесконечно — обычно он деактивируется, когда завершается связанная с ним сессия пользователя. 

Сразу после этого key отправляется в квери-параметре на поддомен persiq.vk.com, который уже связан с непосредственно аутентификацией через VK ID. У этого запроса тоже есть механизм long polling — мы ждем дальнейших действий пользователя. Ключ в таком запросе нужен как раз для того, чтобы поддерживать и проверять соединение в фоновом режиме.

Key отправляется на persiq.vk.com в ожидании следующих событий
Key отправляется на persiq.vk.com в ожидании следующих событий

Второй шаг

Мы получили от VK все нужные токены и данные. Теперь можно нажать кнопку «Продолжить как….». 

Для начала по клику отправляется запрос к уже знакомому нам поддомену api.vk.com

В этот раз запрос достаточно сложный — серверу приходится оперировать большим объемом данных, ведь нужно верифицировать сразу несколько токенов. Поэтому в таком запросе используется метод execute. Он нужен для выполнения кода, «в котором может происходить вызов других API-методов с сохранением и обработкой промежуточных результатов» (подробнее можно почитать в документации VK).

К api.vk.com отправляется запрос с методом execute
К api.vk.com отправляется запрос с методом execute

В теле запроса отправляется UUID, access token и silent token — то есть мы проверяем все ключевые данные, которые сам VK предоставил нам на предыдущем этапе. 

В запросе передается UUID, access token и silent token
В запросе передается UUID, access token и silent token

По сути клиент нашего сайта спрашивает у бэкенда VK: «Ты недавно присваивал вот этому пользователю несколько токенов. Сейчас он пришел и просит пустить его в аккаунт — подтверждаешь, что это те самые токены?». Сервер VK обрабатывает данные с помощью своего внутреннего скрипта.

Ответ приходит положительный — Status Code: 200. Это значит, что access token и silent token, привязанные к нашему запросу авторизации, верные.

Теперь эту бесценную информацию («ура! у нас есть доступ!») нужно каким-то образом передать серверу «Битвы покемонов», чтобы он направил нас в профиль пользователя на сайте pokemonbattle.ru. Для этого потребуется механизм редиректа.

К api.pokemonbattle.ru отправляется запрос, основная задача которого — перенаправить все полученные и подтвержденные данные от сервера VK к нашему бэкенду. В query-параметрах запроса передается UUID, ID пользователя VK и silent token.

На сервер «Битвы покемонов» отправляется запрос с данными, которые ранее подтвердил сервер VK
На сервер «Битвы покемонов» отправляется запрос с данными, которые ранее подтвердил сервер VK

Видим статус-код 302 и описание во вкладке Response — это значит, что запрос успешно перенаправлен.

Видим сообщение о редиректе в ответе
Видим сообщение о редиректе в ответе

А куда именно происходит редирект? Переходим к последнему шагу.

Третий шаг

Этот этап проходит полностью незаметно для пользователя: не нужно нажимать кнопки или вводить данные.

«Битва покемонов» устроена так, что каждому пользователю присваивается так называемый session ID — айди сессии тренера покемонов. Он дает право на доступ к игре: созданию покемонов и участию в битвах. С session ID тренера связаны все остальные данные — в том числе ID профиля VK, который пользователь привязал к своему аккаунту.

Получается задача нашего сервера на этом этапе выглядит так: 

  • узнать ID пользователя в VK

  • отнести этот ID в базу данных и найти совпадение 

  • забрать session ID, который соответствует найденному VK ID

  • провести авторизацию тренера в соответствующем профиле — без каких-либо действий со стороны пользователя

Для начала — откуда наш бэкенд узнает, какой VK ID искать? Самое время вспомнить о том запросе с редиректом, который перенаправил на наш сервер данные, подтвержденные VK. В его квери-параметрах содержался ID профиля VK. Наш бэкенд получил эту информацию, поэтому теперь он может обратиться к базе данных с просьбой найти тренера с нужным VK ID. 

В SQL-запросе к базе данных передается ID пользователя в VK
В SQL-запросе к базе данных передается ID пользователя в VK

Таким образом сервер проверяет: существует ли в принципе тренер, у которого к аккаунту привязан вот такой ID профиля в VK? Если пользователь нашелся, забираем из записи в базе данных его session ID.

Сразу после этого в нашей системе отправляется «тихий» системный запрос формата document, главная задача которого — инициировать JavaScript, отвечающий за авторизацию. В пути такого запроса передается тип авторизации — registration-vk и session_id тренера из базы данных. 

Отправляется «тихий» системный запрос с айди сессии тренера
Отправляется «тихий» системный запрос с айди сессии тренера

Наконец, этот скрипт запускает собственно авторизацию на сайте: 

  • отправляется запрос к микросервису api.pokemonbattle.ru с session_id тренера в body — в ответ приходят все остальные данные профиля

  • отправляются запросы для получения html-файла и наполнения сайта, отрисовывается главная страница — в правом верхнем углу видим аватар и номер пользователя

Авторизация успешно осуществилась.

И как это тестировать?

Фух, кажется разобрались. 

Авторизация через сторонние сервисы — действительно непростая штука с точки зрения логики на бэке. Зато это отличный шанс попрактиковаться в интеграционном тестировании: ведь мы будем проверять взаимодействие двух систем — нашего «родного» сайта и постороннего VK.

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

Для начала по традиции обращаемся к документации. У VK ID она лежит вот тут. Ручному тестировщику может не пригодиться часть сложных инструкций оттуда — они нужны в первую очередь разработчикам. Зато всегда полезно знать о требованиях к кнопке входа и почитать про виды допустимых токенов. 

Начинаем с позитивных кейсов: 

  1. У пользователя есть аккаунт в игре «Битва покемонов» и привязанный к этому аккаунту профиль VK. Если пользователь авторизован в своем профиле VK в тестируемом браузере, он должен пройти ровно по пути, описанному выше — нажать две кнопки и оказаться в своем аккаунте в игре. 

  2. Если пользователь еще не авторизован в VK, то после нажатия первой кнопки должна открываться форма для авторизации VK. Обратим внимание, что авторизоваться можно двумя способами — через QR-код и по номеру телефона. Следует проверить, что оба способа работают и позволяют в дальнейшем успешно авторизоваться в «Битве покемонов».

  3. Также проверим, чтобы корректно обрабатывалась смена аккаунта — если у нас два тренера и к обоим привязаны разные профили VK. Можно в одном и том же браузере попробовать зайти в один аккаунт через VK ID, затем выйти из него и зайти в другой аккаунт уже с другим VK ID. Мы должны попадать к разным тренерам без каких-либо ошибок и путаницы в куки.

  4. Не забудем проверить отмену авторизации: что будет, если пользователь вернулся через браузерную кнопку назад на любом из этапов, если он закрыл страницу до завершения авторизации? Такое поведение нужно корректно обрабатывать: предыдущие страницы должны открываться без ошибок, а в результате незаконченной авторизации не должны создаваться сессионные куки на сайте игры.

  5. Наконец, стоит обратить внимание на время жизни session_id — правильно ли оно установилось в результате авторизации. В «Битве покемонов» session_id живет один год, но чаще всего в приложениях другие, более короткие сессионные куки. Нужно удостовериться, что после входа через VK ID срок жизни авторизационных куки соответствует требованиям.

Теперь посмотрим на негативные проверки. 

  1. Что если наш аккаунт VK не привязан к аккаунту в «Битве покемонов»? В таком случае, даже если у нас есть активные аккаунты отдельно в VK и в «Битве покемонов», авторизация не осуществляется. Вместо этого приложение отправляет пользователя на страницу регистрации с помощью VK ID.

  2. А еще проверим такой сценарий: пользователь успешно авторизовался в «Битве покемонов» через VK ID, затем вышел из аккаунта тренера и пытается авторизоваться через другой VK ID, который не привязан к этому аккаунту тренера. Таким образом, мы убедимся, что куки предыдущей сессии удалились и авторизоваться через чужой VK ID уже не получится.

  3. Протестируем устойчивость авторизации: например, можно выйти из своего профиля в игре. Затем одновременно открыть несколько вкладок со страницей авторизации через VK ID и зайти в профиль в одной из них. Если между вкладками происходит корректный обмен данными, то успешная авторизация в одной вкладке даст авторизацию в остальных (возможно, для этого придется обновить страницу — это нормальное поведение). 

  4. Работу куки можно также проверить, перейдя в режим инкогнито в браузере либо удалив куки вручную в хранилище (вкладка Application в Chrome Devtools). Без них не должна срабатывать та самая silent-авторизаций, о которой мы говорили выше — нужно заново авторизоваться в VK. 

  5. Еще один негативный сценарий — удалить в приложении аккаунт, к которому был привязан профиль VK. Если аккаунт больше неактивен, авторизация через VK ID не должна его «возродить». Конкретно в нашей игре свой аккаунт удалить нельзя, но если вы проверяете интеграцию VK ID с приложением, где профили можно удалять, стоит провести такую проверку. 

  6. Похожий сценарий — попробовать отвязать аккаунт тренера от профиля VK. Если мы успешно авторизовались в «Битве покемонов» через VK ID, затем в настройках профиля отвязали аккаунт тренера от VK и вышли из аккаунта — система не должна пускать нас обратно в тот же профиль через VK ID. 

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

  8. Также можно попробовать удаление с другой стороны — со стороны VK. Если мы удалим профиль VK, привязанный к тренеру, и зарегистрируем новый с тем же номером телефона, он не должен иметь доступа к «Битве покемонов». Ведь новому профилю VK будет присвоен новый идентификатор. 

  9. Наконец, стоит проверить авторизацию через VK ID на разных браузерах и устройствах — на случай, если в каких-то случаях не поддерживается нужный нам скрипт или нарушается верстка. 

Вместо итогов

Мы разобрали на конкретном примере, как устроена авторизация через VK ID и каким образом можно ее протестировать. Конечно, это далеко не исчерпывающий список кейсов: можно углубиться в нагрузочное тестирование или уделить больше внимания безопасности. К тому же сама интеграция с VK ID может иметь свои особенности в разных приложениях. В любом случае надеемся, что с нашей помощью интеграционное тестирование авторизации стало чуть более понятным и чуть менее пугающим :-)

P.S. А еще мы подготовили для вас большую блок-схему [ссылка], которая иллюстрирует процесс авторизации в «Битве покемонов» через VK ID. Чем нагляднее — тем лучше. 

Теги:
Хабы:
+7
Комментарии3

Публикации