Я пытаюсь использовать библиотеки 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, чтобы запросить его.
To resolve the error "The remote server returned an error: (401) Unauthorized", please try checking the following:
URL-адрес SharePoint Online всегда должен начинаться с HTTPS.
$SiteURL` `=` `"https://crescent.sharepoint.com/sites/marketing"`
Проверьте, есть ли у вас достаточные права и можете ли вы открыть сайт в браузере. Убедитесь, что у вас есть роль администратора SharePoint Online.
Убедитесь, что в клиенте включен устаревший протокол проверки подлинности, если он не включен.
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
Я нашел решение.
Я в основном перебираю все файлы cookie всякий раз, когда браузер переходит на новую страницу, и анализирую все файлы cookie, пока не получу файл cookie fedAuth:
Я создал веб-браузер из System.Windows.Forms.WebBrowser.
В 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
Привет, Все вышеперечисленное верно: URL и разрешения. Я нашел решение, я опубликую его в отдельном комментарии.