Как получить OpenID/OAuth2 токен для тестирования front-end rest сервисов?

    Есть задача нагрузочно потестировать фронтальные веб рест апи. Ресты защищены OAuth с Authorization Code Grant. Значит появляется необходимость наличия валидного токена для Authorization: Bearer TOKEN.
    Вопрос — как его взять? И так это сделать красиво и правильно? Вот тут я не знаю.

    В этой статье я описал то быстрое решение к которому я пришел и которое мне не вполне нравится. Выглядит костыльным, хотя я и не нагуглил ничего серебряного. Поэтому, если вы знаете лучшее решение — обязательно скажите об этом в комментарии… Итак…

    Есть обычная типовая система с веб рест фронтом и типовым Single-Page-Application браузерным клиентом на JS. Аутентификация и авторизация — KeyCloak с Authorization Code Grant + brokering.

    Надо обеспечить регулярное нагрузочное тестирование фронтовых рест сервисов.

    Задача достаточная простая, если у нас есть токены которые мы можем просто вставить в заголовок и использовать JMeter для генерации необходимого потока запросов. Вот тут я и споткнулся, веб браузер получает токен просто и естественно (KeyCloak JS), но как его получить без браузера методом последовательных HTTP запросов и без исполнения JS я так и не понял…
    Токен в системе проверяется непосредственно в рест сервисе, а не на API Gateway. Отключить проверку нельзя ибо нет такой возможностью. Просто тестировать без токена не получится.

    Далее мы подумали, а почему бы не использовать имеющиеся у нас функциональные end-to-end Selenium тесты, но быстро отказались от этого так как необходимый ресурс одновременно работающих браузеров оказался достаточно велик. Для минимум 50 потоков нам нужны были 50Гб + 25 ядер. Однако, это дало нам идею что токен можно получить через Селениум, а далее передать его в JMeter для использования.

    В результате, по быстрому был сделан MVP по следующей схеме:

    • Повышаем время жизни токенов для тестового окружения
    • Отключаем кэши в системе, чтобы сымитировать уникальность пользователей.
    • С помощью Selenium приложения поводим процедуры логина тестовой группы пользователей и сбрасываем в файл их токены. Для чтения токена используем вызов JS через WebDriver — return keykcloak.token;
    • С помощью JMeter проводим нагрузочные тестирования с использование токенов пользователей
    • Отчет JMeter всем нравиться



    Мы поставили время жизни токенов в 36 часов. Вторичный код авторизации забираем напрямую из соответствующей базы. Время логина одного пользователя составляет около 10 сек, что дает нам 360 токенов в час. Это позволяет при желании легко подготовить их достаточное количество.

    Сейчас, оператор запускает на выделенном ноутбуке селениум для сбора токенов на ночь, и на утро подготовленный файл токенов готов и можно запускать JMeter для нагрузки.
    Схема работает, заказчик доволен простотой и дешевизной решения, и предлагает перенести это уже на нормальные рельсы с парой контейнеров и запуском из Jenkins.

    А мне вот решение кажется кривым. Ну должен же быть способ обойтись без селениума! Напишите если кто знает. Я не смог ничего нагуглить на тему тестирования OpenID&OAuth2 именно с Authorization Code Grant.

    Средняя зарплата в IT

    120 000 ₽/мес.
    Средняя зарплата по всем IT-специализациям на основании 6 322 анкет, за 1-ое пол. 2021 года Узнать свою зарплату
    Реклама
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее

    Комментарии 27

      +1
      Быть может, вы это искали: Keycloak: JWT token using curl post.
        0
        его скрипт использует grant_type=password, у меня нет возможности включить этот грант. Также подозреваю что это не сработает так как у нас brokering на другой авторизационный сервер. Но идея понятная. Попробую
        0
        У oauth есть password autorization grant. Там никаких редиректов нет, просто REST запрос с логином/паролем клиента и пользователя.
          0
          Согласен. Но у нас используется brokering и логин/пароль вводится на странице другого сервиса, который нам не разрешили изменить. Keycloak ничего о паролях не знает. Включение password autorization grant ничего не даст. Я так вижу ситуацию счас.
            +1
            Вы можете попытаться сэмулировать стандартный authorization code grant.
            1 Делаем запрос на ендпоинт authorize
            2 Реверсиженирим страницу регистрации и смотрим какие запросы для авторизации делает страница. Скорее всего это будет один или несколько POST запросов. В самом последнем в ответе будет authorization code.

            ЗЫ: Вся сложность конечно в эмуляции страницы регистрации. Например, keycloak использует куку и POST запросы с параметром состояния их легко сэмулировать скриптом.
              0
              Да, согласен. Выглядит как не такой уж простой путь по затратам. Умышленно пока его избегал. Надеялся что все уже давно порешали -)
          0
          Поэтому если мы хотим напрямую проводить тесты через фронтальный rest нам нужен этот токен. Вопрос — как его взять? И так это сделать красиво и правильно? Вот тут я не знаю.

          Подождите, а в чем проблема-то вообще? Эти токены получаются по стандартному протоколу, который в клиенте реализуется без особых размышлений.


          PS


          Сейчас трудно встретить систему в которая бы не была rest и не использовала OAuth.

          Но вообще, конечно, очень легко. Вы что, не видели сервисов за api key?

            +1
            Да Сергей. Именно так мы и видели ситуацию неделю назад.
            Если под клиентом понимать js исполняемый в браузере, то, согласен, без проблем. Можете подсказать где в JMeter есть клиент в котором можно реализовать? Тут в качестве клиента используется selenium.
              0
              Можете подсказать где в JMeter есть клиент в котором можно реализовать?

              А откуда взялось требование про JMeter? Написано "тесты на фронтальный rest". В любом тестовом инструменте, в котором вы можете написать обращение по HTTP, результаты которого использовать потом, вы можете запросить свой токен.


              Я, правда, смотрю, вы пишете, вам неподконтролен сервис, который эти токены выдает… ну что же, тогда вы обречены. Но это проблема того, как вы построили тесты.

                0
                там написано нагрузочные тесты. но это в данном случае не важно.
                  0

                  Вот именно потому, что вам нужны нагрузочные тесты, сервис авторизации надо просто подменить. Вы же не его тестируете?

                    0
                    Да конечно была такая идея. Пока нереализуема организационно.
            +1
            Надо обеспечить регулярное нагрузочное тестирование фронтовых рест сервисов.
            [...]
            А мне вот решение кажется кривым. Ну должен же быть способ обойтись без селениума! Напишите если кто знает. Я не смог ничего нагуглить на тему тестирования OpenID&OAuth2 именно с Authorization Code Grant.

            Ваша проблема в том, что у вас задача кривая, потому и решения кривые. Если вам нужно нагрузочное тестирование, вам не нужно тестировать authorization code flow (вы же сервисы тестируете, а не авторизацию?). Соответственно, вы делаете так, чтобы его не было — получая токены любым другим способом.

              –1
              Узнаю архитектурный подход -))) Задача вполне прямая. Нагрузить систему целиком со всеми компонентами. Системное тестирование, не компонентное. И мудрим мы потому что прямая эмуляция пользовательской нагрузки через браузеры и стоит дохера, и в амазоне арендовать сервера на часок не дают.

              Но это неважно. Вижу вы архитектор. Вот вы как бы организовали решение? Ну или задачу выпрямили? Мне бы вот подсказку как любым другим способом токены получить!

              зы. Дык Селениум в нагрузочном тестировании счас не участвует. Он известным мне способом получает токены. Стабильно, дешево и надежно. И любые другие способы я вот и ищу.
                +1
                Задача вполне прямая. Нагрузить систему целиком со всеми компонентами.

                Тогда вы должны нагружать систему авторизации ровно так, как она будет использоваться — то есть через браузер.


                Вот вы как бы организовали решение? Ну или задачу выпрямили?

                Выкинул бы сервер авторизации из тестирования. Или, по крайней мере, минимизировал его участие, заменив auth code flow на более простой — например, на resource owner credentials, если вам нужен пользователь обязательно.

              +1

              Так Keycloak умеет оффлайн токены, которые один раз получил и используй.

              +1

              На самом деле есть куда более простой способ. Поскольку как уже выяснили, вы не тестируете авторизацию, гораздо проще самостоятельно генерить нужный токен. У вас должен быть публичный ключ, зашитый в рест приложении. Сгенерируйте новую пару private/public key и публичный ключ подложите в свое приложение, а приватным подписывайте генерируемые токены.

                0
                У вас должен быть публичный ключ, зашитый в рест приложении.

                С чего бы вдруг? Речь, вроде об OAuth 2/OIDC, там такое совершенно не обязательно. Все зависит от того, что там за токены, и как их валидируют.

                  0
                  Если вы имеете в виду JWS (JWT без части signature), т.е. иначе говоря просто набор каких-то клэймов, то я думаю у автора и не возникло бы проблем с генерацией такого токена, достаточно взять любую библиотеку. Если signature есть но на бэкенде не проверяется подпись токена, а просто считываются клэймы — аналогично. Насколько мне известно, это довольно редкие случаи, т.к. в основном jwt используется именно в виде 3 компонентов, включая подпись, которую как раз и расшифровывают с помощью публичного ключа. Поправьте, если ошибся.
                    +1

                    Я имею в виду, что авторизационный токен (в OAuth 2) вообще не обязан быть JWT, это может быть reference token, который проверяется через валидационный эндпойнт. А может быть JWT, но все равно проверяться через валидационный эндпойнт.


                    Но даже если там JWT, который используется как self-contained, то есть валидируется подпись и клеймы, то публичный ключ в приложение (обычно) не зашиваются, потому что это резко усложняет его отзыв при компроментации. Публичные ключи обычно лежат в общедоступном месте OP, откуда периодически и забираются; логика, по которой определяется доверенный OP, может быть разной. Если автор поста, по его словам, не может подменить авторизационный сервис, то ожидать, что он сможет подменить публикуемые этим сервисом ключи, я бы не стал.

                      0
                      В целом соглашусь с вашей точкой зрения, кроме того что «обычно лежат в общедоступном месте». Лично я чаще видел другую практику, когда публичный ключ для проверки подписи токена либо лежит где-нибудь в aws secret manager (или аналогичных сервисах), либо шьётся как например переменная окружения.
                        +1
                        кроме того что «обычно лежат в общедоступном месте»

                        OpenID Provider Metadata, значение jwks_uri: "REQUIRED. URL of the OP's JSON Web Key Set [JWK] document. This contains the signing key(s) the RP uses to validate signatures from the OP." Что характерно, Google, Microsoft (Azure AD), Okta, OneLogin, IdentityServer и даже, если я не ошибаюсь, используемый автором поста Keycloak — все это поддерживают и выставляют.


                        Лично я чаще видел другую практику, когда публичный ключ для проверки подписи токена либо лежит где-нибудь в aws secret manager (или аналогичных сервисах), либо шьётся как например переменная окружения.

                        Непонятно, какой с этого профит. А если авторизационный сервис еще и не ваш, то будет постоянная проблема поддерживать эти настройки актуальными.

                0

                А в чем проблема получить токен с помощью постпроцессора JMeter? "Открываем" нужную страницу, ищем на ней токен, записываем в переменную и используем ее там, где необходимо. Может быть я не понял задачу, но я всегда делаю именно так

                  –1
                  I can not just open a page because there is js that should be executed.
                  By the way, overall, we decided to use selenium pretest step to collect all needed tokens.
                  Because it works very well and could be easily maintenance of juniors.
                    0
                    Я понимаю ваше сарказм. Но мне приходилось работать с самыми разными типами авторизации, получением токенов и т.д. Выполненный JS в любом случае что-то куда-то отсылает и получает в ответ токен. Да, не всегда это получается прямо и без бубна, но получается всегда. Даже если нет готового решения всегда можно его написать. Благо JMeter поддреживает java, js и groovy (я не говорю о написании своего плагина — трудозатраты возможно не будут сопоставимы с выгодой). Кроме того, если без браузера никак — можно запускать его прямо из сценария JMeter, получать токен и снова выключать — это будет меньшим костылем, но все-таки костылем

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое