2017-01-13 12 views
4

Я работаю над проектом, где они проходят аутентификацию через SAML от OKTA. Я успешно получил интеграцию, где SAMLResponse отправлен (через метод POST) на веб-сайт.Как получить ответ SAML от OKTA для тестирования модулей/интеграции

В настоящей моде TDD я начал с написания некоторых модульных тестов. В моих модульных тестах используется SAMLResponse (который кодируется Base64). Тем не менее, все мои модульные тесты работают, потому что SAMLResponse имеет только срок службы (истекает) в течение нескольких минут, мои тесты модулей прерываются через несколько минут.

Поэтому мне нужно периодически регистрироваться в OKTA, а затем использовать инструменты Chrome dev для отслеживания трафика, отправляемого на мой dev-сайт. Затем я копирую и вставляю SAMLResponse в свои модульные тесты и возвращаюсь к прохождению модульных тестов. Очевидно, что это не желательная ситуация.

Итак, мой вопрос: как я могу войти в Okta автоматическим способом (желательно на C#), чтобы получить SAMLResponse? Я предполагаю, что есть какой-то URL-адрес, с которым я могу отправить сообщение POST с именем пользователя и паролем и вернуть SAMLReponse. Все попытки моего Фиддлера попытаться понять, что требуется для общения, оставили меня разочарованным. Я ищу любое руководство, которое у вас может быть. Заранее спасибо.

+0

Я не знаком с SAML, но из вашего вопроса я думаю, что вы либо тестируете на некорректном уровне, либо нуждаетесь в дальнейшей абстракции. Я бы увидел, что там, где вы обрабатываете ответ, не должно иметь значения в фактическом сообщении, но больше на содержании сообщения, то есть быть в состоянии подделать ответ, должен работать. Я бы никогда не ожидал, что единичный тест придется когда-либо вызывать внешнюю функцию, и он будет вызывать сигналы тревоги, если он должен был войти в внешнее приложение. –

+0

Согласовано. Это действительно становится интеграционным тестом. Если SAMLResponses не истекает, это действительно может быть единичным тестом, но, согласно Okta, это не вариант. Учитывая сложность интеграции SAML, мы полагаемся на наши тесты для поиска проблем с конфигурацией на еженедельной основе. –

+0

Относительно вашего комментария о возможности «подделать» ответ. Это было то, что я изначально пытался, однако ответы (которые являются только строками Base 64) содержат информацию, подписанную сертификатом. Поэтому, если вы измените что-либо ответ, проверка не завершится. Я знаю, что я нарушаю некоторые практические рекомендации по единичному тестированию, но я также поддерживаю SAML и OKTA, но все равно не собираюсь сдаваться на интеграционных тестах, поскольку я получаю от них такую ​​большую ценность ... просто хочу, чтобы они были автоматизирован. –

ответ

4

Я придумал рабочее решение и хотел поделиться им с сообществом. Я не уверен в протоколе для ответа на свой вопрос, основываясь на полезных отзывах других авторов (Joël Franusic). Если я нарушаю протокол, сообщите мне.

Благодаря Joël Franusic для указателей. Я реализовал его решение 1.2 (User Agent с клиентом Okta). Между его ссылками и несколькими другими документами на веб-сайте Okta мне удалось в конечном итоге собрать вместе рабочий код.

private static async Task<string> GetTestSamlResponse() 
    { 
     try 
     { 
      // settings specific to my Okta instance 
      string username = "USERNAME GOES HERE"; 
      string password = "PASSWORD GOES HERE"; 
      var apiToken = "API TOKEN GOES HERE"; 

      // this is the unique domain issued to your account. 
      // If you setup a dev account you'll have a domain in the form https://dev-<AccountNumber>.oktapreview.com. 
      // account number is a unique number issues by Okta when you sign up for the account 
      var baseUrl = "YOUR BASE URL GOES HERE"; 

      // In Okta Admin UI, click "Applications" in main menu, choose your app, click "Sign On" tab. Under Sign On Methods, then under SAML 2.0, click "View Setup Instructions" 
      // Get the url called "Identity Provider Single Sign-On URL", paste it in th below line 
      var ssoUrl = "YOUR SSO URL GOES HERE"; 

      // construct an Okta settings object 
      var settings = new Okta.Core.OktaSettings 
      { 
       ApiToken = apiToken, 
       BaseUri = new Uri(baseUrl) 
      }; 

      // get session token from Okta 
      var authClient = new Okta.Core.Clients.AuthClient(settings); 
      var authResponse = authClient.Authenticate(username, password); 
      var sessionToken = authResponse.SessionToken; 

      // start session and get a cookie token 
      var sessionsClient = new Okta.Core.Clients.SessionsClient(settings); 
      var session = sessionsClient.CreateSession(sessionToken); 
      var cookieToken = session.CookieToken; 

      // using the cookie token, get the SAMLResponse from Okta via a HTTP GET. 
      var httpClient = new System.Net.Http.HttpClient(); 

      // add User-Agent header, because apparently Okta is expecting this information. 
      // If you don't pass something, the Okta site will return a 500 - Internal Server error 
      httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "UnitTest"); 

      // add the cookie token to the URL query string 
      string url = string.Format("{0}?onetimetoken={1}", ssoUrl, cookieToken); 

      // do the HTTP GET 
      using (var response = await httpClient.GetAsync(url)) 
      { 
       if (response.StatusCode == HttpStatusCode.OK) 
       { 
        // read the HTML returned 
        string html = await response.Content.ReadAsStringAsync(); 

        // parse the HTML to get the SAMLResponse (using HtmlAgilityPack from NuGet) 
        HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument(); 
        htmlDoc.LoadHtml(html); 
        // from the input field called SAMLResponse, get the "value" attribute 
        string samlResponse = htmlDoc.DocumentNode.SelectSingleNode("//input[@name='SAMLResponse']").Attributes["value"].Value; 
        return samlResponse; 
       } 
       else 
        throw new Exception(string.Format("Error getting SAML Response {0}", response.StatusCode)); 
      } 
     } 
     catch (Exception ex) 
     { 
      throw; 
     } 
    } 
2

Есть несколько способов сделать вид тестирования, которые вы предлагаете, вот то, что приходит на ум сразу:

  1. Написать простой HTTP «Агент пользователя» в C# с использованием библиотеки как RestSharp или аналогичный.
  2. Постройте интеграционный тест против внешнего ложного IdP.
  3. Измените SAMLResponse и перепишите его собственным ключом.

Я подробно рассмотрю каждый подход в деталях ниже.

Написание простого HTTP «User Agent»

я предлагаю этот метод, я предлагаю принимать одну из следующих двух подходов:

  1. Написать общий User Agent, который будет обнаруживать и заполнить имя пользователя и поля формы пароля. Я написал инструмент в Python под названием «saml-messenger», который использует этот подход, основной код находится в файле с именем messenger.py.
  2. Используйте API Okta для получения токена сеанса и используйте его для получения SAMLResponse. Проект okta-aws-cli-assume-role использует этот подход. Код для fetching the session token и exchanging that session token for a SAMLResponse находятся в файле src/main/java/com/okta/tools/awscli.java.

Первый подход более общий и должен работать с любым IdP с полем имени пользователя и пароля. Второй подход, скорее всего, то, что вы ищете, но относится к Okta.

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

Построение интеграционного теста против макета IdP

Этого подхода будет иметь вы создали макет IdP, который даст вам SAMLResponse без аутентификации, я использовал проект saml-idp сделать это раньше.

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

Изменение повторно подписания SAMLResponse

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

 Смежные вопросы

  • Нет связанных вопросов^_^