Запрос локальной среды SharePoint с помощью Azure AD MFA через приложение C#

Я пытаюсь использовать библиотеки Microsoft.Identity.Client и Microsoft.SharePoint.Client для аутентификации на локальном сервере SharePoint, а затем запрашиваю его.

Я получаю токен доступа Azure AD, частью которого является сервер SharePoint, как показано ниже:

private readonly string[] m_scopes = { "user.read", "https://sql.azuresynapse-dogfood.net/user_impersonation" };

var publicAppBuilder = PublicClientApplicationBuilder.Create("MyClientId").WithAuthority("https://login.microsoftonline.com/a******com.onmicrosoft.com"); 
 
publicAppBuilder.WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient"); 

var app = publicAppBuilder.Build();

AuthenticationResult result = null;

result = app.AcquireTokenInteractive(m_scopes).ExecuteAsync().GetAwaiter().GetResult();
if (result != null)
{
    m_mediator.AccessToken = result.AccessToken;
}

Когда я получаю токен доступа, я помещаю его в заголовок запроса следующим образом:

args.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + m_mediator.AccessToken;

Что находится внутри метода подписки ClientContext.ExecutingWebRequest:

clientContext.ExecutingWebRequest += (sender, args) =>

который вызывается

context.ExecuteQuery();

The remote server returned an error: (401) Unauthorized. or The remote server returned an error: (403) Forbidden.

Как я могу установить соединение? Я хочу избежать использования регистрации только для приложений, я хочу пройти аутентификацию с помощью метода Azure AD MFA (интерактивный). Обратите внимание, что у меня есть все необходимые разрешения, и я являюсь администратором как в Azure AD, к которой присоединен SharePoint, так и в Сам сервер SharePoint. Я аутентифицируюсь через браузер просто отлично.

Я пробовал несколько вещей до сих пор:

  • Я попытался создать отдельный запрос, в котором я пересылаю ранее полученный токен доступа в качестве авторизации: токен носителя

  • Я попытался прочитать FedAuth из окна подключения для аутентификации, поэтому я могу переслать его в своем HTTP-запросе, но безуспешно.

  • Я попытался создать «веб-браузер» с помощью класса C# WebBrowser и прочитать файлы cookie на уровне браузера, например: cookieContainer = webBrowser1.Document.Cookie; но безуспешно.

Я ожидаю пройти аутентификацию через Azure AD, а затем подключиться к SharePoint, чтобы запросить его.

Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
0
0
81
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

To resolve the error "The remote server returned an error: (401) Unauthorized", please try checking the following:

  • Проверьте правильность вашего URL:

URL-адрес SharePoint Online всегда должен начинаться с HTTPS.

$SiteURL`  `=` `"https://crescent.sharepoint.com/sites/marketing"`
  • Проверьте, есть ли у вас права доступа к сайту:

Проверьте, есть ли у вас достаточные права и можете ли вы открыть сайт в браузере. Убедитесь, что у вас есть роль администратора SharePoint Online.

  • Проверьте, включен ли протокол аутентификации Legacy:

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

Справка : SharePoint Online: исправление ошибки «Удаленный сервер вернул ошибку (401) несанкционировано» в PowerShell — Дневник SharePoint

To resolve the error "The remote server returned an error: (403) Forbidden.", please try checking the following:

  • Убедитесь, что вы указали правильный URL-адрес и учетные данные.

  • Убедитесь, что у вас установлена ​​последняя версия SDK клиентского компонента SharePoint Online.

  • Попробуйте явно добавить себя на сайт

  • Проверьте статус блокировки вашего сайта и разблокируйте, если он заблокирован.

  • Проверьте, включены ли какие-либо политики условного доступа в вашем арендаторе.

  • Если вы пытаетесь подключиться к сайту администратора арендатора, убедитесь, что указан URL-адрес администратора арендатора, как показано ниже:

       https://YourDomain-admin.sharepoint.com  
    

Справка : SharePoint Online: исправление «Удаленный сервер вернул ошибку: (403) Запрещено». Ошибка в PowerShell — дневник SharePoint.

Привет, Все вышеперечисленное верно: URL и разрешения. Я нашел решение, я опубликую его в отдельном комментарии.

Andrija Peric 08.04.2022 10:42
Ответ принят как подходящий

Я нашел решение.

Я в основном перебираю все файлы cookie всякий раз, когда браузер переходит на новую страницу, и анализирую все файлы cookie, пока не получу файл cookie fedAuth:

  1. Я создал веб-браузер из System.Windows.Forms.WebBrowser.

  2. В WebBrowserNavigatedEventHandler для Navigated я делаю следующее:

    если (webBrowser1.Url.AbsoluteUri == "о: пусто") { возврат; }

    var cookieData = GetWebBrowserCookie.GetCookieInternal(webBrowser1.Url, false);

    если (string.IsNullOrEmpty(cookieData) == false) { var dict = ParseCookieData(cookieData); если (dict.ContainsKey("FedAuth") && !string.IsNullOrEmpty(dict["FedAuth"])) { m_mediator.FedAuthCookie = dict["FedAuth"]; если (dict.ContainsKey("rtFa") && !string.IsNullOrEmpty(dict["rtFa"])) { m_mediator.RtFaCookie = dict["rtFa"]; } m_mediator.Обновлениеконфигурации(); это.Закрыть(); } }

Метод ParseCookieData выглядит следующим образом:

private IDictionary<string, string> ParseCookieData(string cookieData)
{
  var cookieDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

  if (string.IsNullOrEmpty(cookieData))
  {
    return cookieDictionary;
  }

  var values = cookieData.TrimEnd(';').Split(';');
  foreach (var parts in values.Select(c => c.Split(new[] { '=' }, 2)))
  {
    var cookieName = parts[0].Trim();

    var cookieValue = parts.Length == 1 ? string.Empty : parts[1];

    cookieDictionary[cookieName] = cookieValue;
  }

  return cookieDictionary;
}

и класс GetWebBrowserCookie выглядит так:

[SecurityCritical]
public static string GetCookieInternal(Uri uri, bool throwIfNoCookie)
{
  uint pchCookieData = 0;
  string url = UriToString(uri);
  uint flag = (uint)NativeMethods.InternetFlags.INTERNET_COOKIE_HTTPONLY;

  //Gets the size of the string builder   
  if (NativeMethods.InternetGetCookieEx(url, null, null, ref pchCookieData, flag, IntPtr.Zero))
  {
    pchCookieData++;
    StringBuilder cookieData = new StringBuilder((int)pchCookieData);

    //Read the cookie   
    if (NativeMethods.InternetGetCookieEx(url, null, cookieData, ref pchCookieData, flag, IntPtr.Zero))
    {
      DemandWebPermission(uri);
      return cookieData.ToString();
    }
  }

  int lastErrorCode = Marshal.GetLastWin32Error();

  if (throwIfNoCookie || (lastErrorCode != (int)NativeMethods.ErrorFlags.ERROR_NO_MORE_ITEMS))
  {
    throw new Win32Exception(lastErrorCode);
  }

  return null;
}

private static void DemandWebPermission(Uri uri)
{
  string uriString = UriToString(uri);

  if (uri.IsFile)
  {
    string localPath = uri.LocalPath;
    new FileIOPermission(FileIOPermissionAccess.Read, localPath).Demand();
  }
  else
  {
    new WebPermission(NetworkAccess.Connect, uriString).Demand();
  }
}

private static string UriToString(Uri uri)
{
  if (uri == null)
  {
    return string.Empty;
  }

  UriComponents components = (uri.IsAbsoluteUri ? UriComponents.AbsoluteUri : UriComponents.SerializationInfoString);
  return new StringBuilder(uri.GetComponents(components, UriFormat.SafeUnescaped), 2083).ToString();
}

Таким образом, мы открываем всплывающий веб-браузер C#, аутентифицируем пользователя через Интернет с помощью MFA, а затем закрываем браузер, когда получаем файл cookie аутентификации, чтобы мы могли продолжить работу с HTTP-запросами к серверу Sharepoint.

Источник: https://github.com/OceanAirdrop/SharePointOnlineGetFedAuthAndRtfaCookie

Другие вопросы по теме