Решаемая задача
Язык VBA встроен во все офисные приложения, не смотря на свою кажущуюся устарелость, востребован при анализе информации, особенно числовой, финансовой. Это особенно востребовано в больших организациях, которые просто не успевают воплотить идеи работников по автоматизации их работы. Обычно, анализом занимаются подразделения, отвечающие за составление отчетности. Автоматизация их работы никогда не является приоритетом, не помогает даже RPA. Работникам, как и прежде, удобно воспользоваться Excel, Outlook для решения своих задач, а также автоматизировать рутинные операции с использованием языка VBA.
Перед тем, как анализировать информацию на VBA, ее необходимо собрать из разных источников. Самый простой механизм аутентификации – Basic. Он описан во множестве статей. Но в корпоративной экосистеме для аутентификации пользователей чаще применяют Kerberos аутентификацию, а в последнее время стала популярной аутентификация по протоколу OpenIdConnect (OIDC).
В статье рассмотрим методику анализа протокола аутентификации OpenIdConnect и самого популярного механизма авторизации – Authorization code flow, а также разработку приложения на языке VBA, осуществляющего за пользователя такую аутентификацию для последующего сбора данных из корпоративных систем. В статье есть код, который можно переиспользовать, но ввиду отличий в корпоративных инфраструктурах организаций, начать необходимо с анализа контекста организации, применяемых настроек протокола аутентификации.
Решая аналогичную проблему, у меня не получилось найти готовых решений ни на русском, ни на английском языке. Кроме Basic аутентификации на VBA, иной информации нет. Пришлось пройти путем экспериментов и потратить около 8 часов на изучение вопро��а и воспроизведение протокола аутентификации OIDC на языке VBA. Надеюсь, информация в этой статье позволит сэкономить ваше время. Статья будет полезна как опытным разносторонним разработчикам с широким кругозором, а также начинающим специалистам по VBA без опыта web разработки. Те моменты, которые могут бы не интуитивны, особенно важны по тексту, заняли время на эксперименты, я выделю жирным. Сразу предупреждаю, что серебряной пули в статье нет, не проведя анализ вашего приложения, просто скопировать код и использовать не получится. Код потребует адаптации.
Анализируем протокол аутентификации
Возможности анализа в корпоративной инфраструктуре часто ограничены. Для анализа воспользуемся встроенными в браузер инструментами. В Chrome и Яндекс браузере - это функция «Исследовать элемент». В Edge – «Проверить». Дальнейшие названия буду приводить на примере Яндекс браузера.
Вначале, посмотрим на аутентификацию в нашем сервисе, назовем его ABC, глазами обычного пользователя. Открываем браузер в режиме инкогнито. Открываем сервис ABC. Протокол OpenIdConnect предполагает перенаправление пользователя для ввода пароля на страницу провайдера аутентификации, назовем его IDP. Эти два названия дальше будем часто использовать, стоит их запомнить (ABC, IDP). IDP предложит пользователю ввести логин и пароль. После ввода логина и пароля, браузер вернет нас обратно на страницу сервиса ABC, где мы увидим интересующие нас данные. Если сеть быстрая, то в большинстве случаем мы увидим 2 действия: страницу аутентификации IDP и страницу сервиса ABC с данными, но на самом деле, действий было гораздо больше. Часто, в корпоративной инфраструктуре используется Kerberos аутентификация, поэтому действий может быть 3. Браузер может дважды спросить пароль.
Подготовимся к анализу трафика. Опытным путем, самым удобным, в данном случае, способом упрощенно зафиксировать происходящее в сети является sequence диаграмма процесса. Хотя бы на бумаге нарисуйте 3х действующих лиц (браузер, ресурс ABC, IDP).
Попробуем разобраться, исследовать сетевой трафик. Закрываем браузер (надо обнулить куки), открываем его заново в режиме инкогнито и заходим на любой сайт, ждем его загрузки. Включаем режим исследования. Там, переключаемся на вкладку Network. Переходим страницу сервиса ABC, браузер опять отобразит страницу аутентификации IDP, но на вкладке Network появится множество строк, обозначающих перехваченные сетевые пакеты. Введем логин и пароль, дождемся загрузки ресурса ABC и остановим перехват трафика в браузере.
Проанализируем перехваченный трафик. Сетевых пакетов много, параметров в них тоже много. Не все пакеты нам интересны, не все параметры имеют отношение к аутентификации. Когда браузер пытается загрузить пользовательский интерфейс страницы ABC, то он скачает как саму страницу, так и различные картинки, css файлы, файлы javascript. Они нас не интересуют. Пойдем сверху вниз, пока не найдем следующие пакеты:
1. Вначале, когда браузер сделает запрос на сервис ABC, тот проверит, есть ли у пользователя токен для аутентификации в блоке cookie. Если токена нет, а в режиме инкогнито его действительно не будет, сервис ABC переправит пользователя на свою страницу аутентификации. Т.е. он может не сразу направить пользователя на IDP, а сначала направить на свой сервис аутентификации. URL такого сервиса может быть: ABC/login например. Т.е. уже на первом шаге есть опциональность, зависящая от конкретного сервиса, его настроек.
2. Сервис аутентификации ABC, если там настроен OpenIdConnect, перенаправит пользователя на IDP, передав в IDP конкретный адрес сервиса ABC, на который надо вернуть пользователя после прохождения аутентификации. Мы не всегда приходим на главную страницу сервиса ABC, у нас может быть ссылка на какой-то внутренний раздел. Смысл такого действия, чтобы пользователя вернуть на страницу, которую он запросил, а не домашнюю страницу сервиса ABC.
3. Часто, для удобства работы пользователей, корпоративные веб приложения используют Kerberos аутентификацию совместно с OpenIdConnect. Опять опциональность. Если она настроена, если тикетов в операционной системе нет, вы не в домене или в режиме инкогнито, то вверху в браузере вы увидите не типичное невзрачное окошко для ввода логина и пароля:

В перехвате могут быть несколько сетевых пакетов связанных с попыткой Kerberos входа. Сложность анализа Kerberos в том, что браузер не видит некоторые Kerberos пакеты, т.к. браузер обращается к API операционной системы для прохождения Kerberos аутентификации (это еще один участник процесса). Мы только увидим, что браузер отправляет пакеты аутентификации, но не сможем понять откуда взялись данные у браузера для генерации этих пакетов. Для полноценного анализа Kerberos нужен снифер, но не каждому разрешат поставить его на рабочий компьютер и для достижения цели по OIDC нам это не очень нужно.
4. После попытки аутентификации в Kerberos, нас перекинет на форму аутентификации IDP. Отобразится обычные web форма аутентификации, основанная на теге form.

5. Введя логин и пароль, мы сгенерируем очередной сетевой пакет.
6. В ответ IDP выдаст браузеру authorization code (параметр code) и средиректит нас на страницу аутентификации сервиса ABC.
7. Дальше, ищем пакет аутентификации на ABC, в котором мы передадим authorization code и получим зашифрованный токен доступа в cookie. Название cookie может быть разным для разных сервисов организации.
8. Все остальные запросы к сервису ABC будут содержать токен и успешно скачивать с сервиса все необходимые данные.
9. В перехвате этого шага вы не увидите, но в случае истечения токена, можно обратиться в IDP за новым authorization code используя Cookie IDP.
Детали приведены на SEQUENCE диаграмме
На диаграмме приведены шаги процесса OIDC+Kerberos аутентификации и важные передаваемые параметры.

Воспроизводим OPENIDCONNECT на языке VBA, получаем тикет. Важные моменты
Весь вышеуказанный процесс необходимо воспроизвести шаг за шагом. Разработку удобно вести в отдельном модуле. Количество шагов на sequence диаграмме и в коде немного отличаются. Но если вы поняли смысл, это не должно доставить сложностей.
Для отладки лучше записывать данные сетевых пакетов в файл, потому самостоятельно. В код включены функции записи информации в файл (myFILE.CreateAfile, myFILE.AppendAFile), подготовьте эти функции самостоятельно, либо удалите их вызов из кода. Использование MsgBox и запись в ячейки EXCEL не удобно для отладки, сетевые пакеты могут быть очень большими.
В коде будет использована библиотека Microsoft WinHttp.WinHttpRequest.5.1.
Особое внимание нужно обратить на выключение редиректа - http.Option(6) = False. Если его не выключить, перенаправления произойдут не явно, вы не сможете прочитать важные параметры промежуточных пакетов и их Cookie, необходимые для дальнейших запросов.
Еще один важный момент – это проставление заголовка с длинной пакета. Если поленитесь его указать, можно потратить много времени на выяснения причины непредвиденных ответов сервера. Используем http.SetRequestHeader "Content-length", "" & ____.
И третий момент, с которым я столкнулся, проверяйте url на который ведет перенаправление. Там могут быть закодированные через апмперсант символы (HTML entities), кодирующие спец.знаки в строке url и не воспринимаемые библиотекой WinHttp.WinHttpRequest.5.1.
В остальном, надо просто воспроизвести то, что видим в перехвате трафика.
Представленный код не претендует на оптимальность, там могут быть не используемые переменные и последовательность отправки пакетов писалась для конкретного корпоративного сервиса.
Определяем переменные
Dim ABCCookies As String Dim ACTION As String Dim AUTH_SESSION_ID As String Dim AUTH_SESSION_ID_LEGACY As String Dim KC_RESTART As String 'куки получаемые от ABC сайта Dim AspNetNonce As String Dim AspNetCorrelation As String Dim session_code As String Dim execution As String Dim tab_id As String 'куки IDP после успешной аутентификации Dim IDP_IDENTITY As String Dim IDP_IDENTITY_LEGACY As String Dim IDP_SESSION As String Dim IDP_SESSION_LEGACY As String 'код авторизации от IDP Dim code As String Dim state As String Dim session_state As String 'искомый токен ABC Dim ABC_Cookie As String Dim ABC_Cookie_Period As String
Основная функция
Function get_ABC_Data(authUser As String, authPass As String, URL As String) As String Dim ret As String Dim r As String myFILE.permitedWrite = True 'включаем логирование r = myFILE.CreateAfile("C:\Users\USERNAME\Desktop\vba\log.txt", "Log ABC Auth") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") If ABC_Cookie = "" Then ret = get_1_ABCCookie(URL) 'запрашиваем куки ABC и ссылку на провайдер аутентификации ret = get_2_IDPGetCookie1 'get запрос аутентификации, получаем куки idp ret = get_3_IDPGetCookie2 'повторно ret = get_4_IDPPost1 'получаем форму ввода пароля ret = get_5_IDPPost2(authUser, authPass) 'получаем код авторизации, который на сл.шаге меняем на токен ret = get_6_ABCAuth 'получаем токен от ABC End If myFILE.permitedWrite = False 'выключаем логирование get_ABC_Data = "" End Function
Функции вызова конкретных пакетов flow
Private Function get_1_ABCCookie(URL As String) As String Dim location As String Dim http As Object Set http = CreateObject("WinHttp.WinHttpRequest.5.1") http.Open "GET", URL, False http.SetRequestHeader "Connection", "keep-alive" http.Option(6) = False 'выключаем редирект, чтобы получить куки от ABC Call http.Send http.waitForResponse 5 'получаем куки AspNetNonce = ".AspNetCore.OpenIdConnect.Nonce." & Split(Split(http.GetAllResponseHeaders, ".AspNetCore.OpenIdConnect.Nonce.")(1), ";")(0) AspNetCorrelation = ".AspNetCore.Correlation." & Split(Split(http.GetAllResponseHeaders, ".AspNetCore.Correlation.")(1), ";")(0) 'получаем адрес перенаправления для следующего запроса ACTION = http.GetResponseHeader("Location") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "" & Now) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- REQUEST 1 ---------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "GET: " & URL) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Connection: keep-alive") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- RESPONSE 1 --------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Status: " & http.status & " " & http.statusText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.GetAllResponseHeaders) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.ResponseText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") get_1_ABCCookie = "" & http.status End Function Private Function get_2_IDPGetCookie1(Optional authUser As String = vbNullString) As String Dim location As String Dim http As Object Set http = CreateObject("WinHttp.WinHttpRequest.5.1") URL = ACTION http.Open "GET", URL, False http.Option(6) = False 'выключаем редирект, чтобы получить куки от ABC http.SetRequestHeader "Connection", "keep-alive" Call http.Send http.waitForResponse 5 'location = http.GetResponseHeader("Location") 'получаем куки AUTH_SESSION_ID = Split(Split(http.GetAllResponseHeaders, "AUTH_SESSION_ID=")(1), ";")(0) AUTH_SESSION_ID_LEGACY = Split(Split(http.GetAllResponseHeaders, "AUTH_SESSION_ID_LEGACY=")(1), ";")(0) KC_RESTART = Split(Split(http.GetAllResponseHeaders, "KC_RESTART=")(1), ";")(0) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "" & Now) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- REQUEST 2 ---------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "GET: " & URL) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Connection: keep-alive") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- RESPONSE 2 --------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Status: " & http.status & " " & http.statusText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.GetAllResponseHeaders) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.ResponseText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") get_2_IDPGetCookie1 = "" & http.status End Function Private Function get_3_IDPGetCookie2(Optional authUser As String = vbNullString) As String Dim location As String Dim http As Object Set http = CreateObject("WinHttp.WinHttpRequest.5.1") URL = ACTION cookie = "" cookie = cookie & "AUTH_SESSION_ID=" & AUTH_SESSION_ID & ";" '& vbNewLine cookie = cookie & "AUTH_SESSION_ID_LEGACY=" & AUTH_SESSION_ID_LEGACY & ";" '& vbNewLine cookie = cookie & "KC_RESTART=" & KC_RESTART http.Open "GET", URL, False http.SetRequestHeader "Cookie", cookie http.SetRequestHeader "Connection", "keep-alive" http.Option(6) = False 'выключаем редирект, чтобы получить куки от ABC Call http.Send http.waitForResponse 5 'location = http.GetResponseHeader("Location") 'получаем куки KC_RESTART = Split(Split(http.GetAllResponseHeaders, "KC_RESTART=")(1), ";")(0) ACTION = Split(Split(http.ResponseText, "ACTION=""")(1), """")(0) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "" & Now) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- REQUEST 3 ---------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "GET: " & URL) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Connection: keep-alive") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Cookie: " & cookie) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- RESPONSE 3 --------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Status: " & http.status & " " & http.statusText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.GetAllResponseHeaders) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.ResponseText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") get_3_IDPGetCookie2 = "" & http.status End Function Private Function get_4_IDPPost1(Optional authUser As String = vbNullString) As String Dim location As String Dim http As Object Dim cookie As String Set http = CreateObject("WinHttp.WinHttpRequest.5.1") URL = ACTION cookie = "" cookie = cookie & "AUTH_SESSION_ID=" & AUTH_SESSION_ID & ";" '& vbNewLine cookie = cookie & "AUTH_SESSION_ID_LEGACY=" & AUTH_SESSION_ID_LEGACY & ";" '& vbNewLine cookie = cookie & "KC_RESTART=" & KC_RESTART http.Open "GET", URL, False http.SetRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" http.SetRequestHeader "Content-type", "application/x-www-form-urlencoded" http.SetRequestHeader "Cookie", cookie http.SetRequestHeader "Connection", "keep-alive" http.SetRequestHeader "Host", "idp.intra.net" http.SetRequestHeader "User-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 YaBrowser/25.8.0.0 Safari/537.36" Call http.Send http.waitForResponse 5 session_code = Split(Split(http.ResponseText, "session_code=")(1), "&")(0) execution = Split(Split(http.ResponseText, "execution=")(1), "&")(0) tab_id = Split(Split(http.ResponseText, "tab_id=")(1), ">")(0) ACTION = Split(Split(http.ResponseText, "action=""")(1), """")(0) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "" & Now) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- REQUEST 4 ---------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "GET: " & URL) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Connection: keep-alive") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Cookie: " & cookie) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- RESPONSE 4 --------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Status: " & http.status & " " & http.statusText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.GetAllResponseHeaders) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.ResponseText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") get_4_IDPPost1 = "" & http.status End Function Private Function get_5_IDPPost2(authUser As String, authPass As String) As String Dim URL As String Dim params As String Dim params_masked As String Dim cookie As String Dim http As Object Set http = CreateObject("WinHttp.WinHttpRequest.5.1") 'случай, когда в url находятся закодированные символы, не воспринимаемые библиотекой WinHttp.WinHttpRequest.5.1 URL = Replace(ACTION, "&", "&") params = "" params = params & "username=" & authUser & "&" params = params & "password=" & authPass & "&" params = params & "credentialId=" params_masked = "" params_masked = params_masked & "username=" & authUser & "&" params_masked = params_masked & "password=*********" & "&" params_masked = params_masked & "credentialId=" cookie = "" cookie = cookie & "AUTH_SESSION_ID=" & AUTH_SESSION_ID & ";" '& vbNewLine cookie = cookie & "AUTH_SESSION_ID_LEGACY=" & AUTH_SESSION_ID_LEGACY & ";" '& vbNewLine cookie = cookie & "KC_RESTART=" & KC_RESTART http.Open "POST", URL, False http.SetRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" http.SetRequestHeader "Content-type", "application/x-www-form-urlencoded" 'длина очень важна http.SetRequestHeader "Content-length", "" & 53 http.SetRequestHeader "Cookie", cookie http.SetRequestHeader "Connection", "keep-alive" http.SetRequestHeader "Host", "idp.intra.net" http.SetRequestHeader "User-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 YaBrowser/25.8.0.0 Safari/537.36" Call http.Send(params) 'http.waitForResponse 5 If http.status = 200 Then IDP_IDENTITY = Split(Split(http.GetAllResponseHeaders, "IDP_IDENTITY=")(1), ";")(0) IDP_IDENTITY_LEGACY = Split(Split(http.GetAllResponseHeaders, "IDP_IDENTITY_LEGACY=")(1), ";")(0) IDP_SESSION = Split(Split(http.GetAllResponseHeaders, "IDP_SESSION=")(1), ";")(0) IDP_SESSION_LEGACY = Split(Split(http.GetAllResponseHeaders, "IDP_SESSION_LEGACY=")(1), ";")(0) ACTION = Split(Split(http.ResponseText, "ACTION=""")(1), """")(0) code = Split(Split(http.ResponseText, "NAME=""code"" VALUE=""")(1), """")(0) state = Split(Split(http.ResponseText, "NAME=""state"" VALUE=""")(1), """")(0) session_state = Split(Split(http.ResponseText, "NAME=""session_state"" VALUE=""")(1), """")(0) End If r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "" & Now) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- REQUEST 5 ---------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "POST: " & ACTION) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Connection: keep-alive") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Content-type: application/x-www-form-urlencoded") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Content-length: 53") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Cookie: " & cookie) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", params_masked) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- RESPONSE 5 --------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Status: " & http.status & " " & http.statusText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.GetAllResponseHeaders) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.ResponseText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") get_5_IDPPost2 = "" & http.status End Function Private Function get_6_ABCAuth(Optional authUser As String = vbNullString) As String Dim URL As String Dim location As String Dim params As String Dim cookie As String Dim http As Object Set http = CreateObject("WinHttp.WinHttpRequest.5.1") 'https://ABC/app0/signin-oidc URL = ACTION params = "" params = params & "code=" & code & "&" params = params & "state=" & state & "&" params = params & "session_state=" & session_state 'MsgBox params cookie = "" cookie = cookie & AspNetNonce & ";" '& vbNewLine cookie = cookie & AspNetCorrelation http.Open "POST", URL, False 'http.SetRequestHeader "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7" http.SetRequestHeader "Content-type", "application/x-www-form-urlencoded" 'длина очень важна http.SetRequestHeader "Content-length", "" & 691 'http.SetRequestHeader "Connection", "keep-alive" http.SetRequestHeader "Cookie", cookie 'http.SetRequestHeader "Host", "ABC" 'http.SetRequestHeader "Origin", "null" 'http.SetRequestHeader "Pragma", "no-cache" 'http.SetRequestHeader "User-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 YaBrowser/25.8.0.0 Safari/537.36" 'очень важно. без этого не отдает код 302 и куки ABC http.Option(6) = False Call http.Send(params) http.waitForResponse 60 MsgBox http.status 'MsgBox http.GetAllResponseHeaders If http.status = 302 Then ABC_Cookie = Split(Split(http.GetAllResponseHeaders, "ABC.WebApplication.Cookies=")(1), ";")(0) Else ABC_Cookie = vbNull End If r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "" & Now) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- REQUEST 6 ---------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "POST: " & URL) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Connection: keep-alive") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Content-type: application/x-www-form-urlencoded") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Content-length: 691") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Cookie: " & cookie) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", params) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "------------------------- RESPONSE 6 --------------------------") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "Status: " & http.status & " " & http.statusText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "HEADERS") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.GetAllResponseHeaders) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "PAYLOAD") r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", http.ResponseText) r = myFILE.AppendAFile("C:\Users\USERNAME\Desktop\vba\log.txt", "") get_6_ABCAuth = "" & http.status End Function
Михаил Левитин, Крупная российская организация
