繁体   English   中英

通过 C# 应用程序使用 Azure AD MFA 查询本地 SharePoint

[英]Querying On-premise SharePoint using Azure AD MFA through C# app

我正在尝试使用 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;
}

当我获得访问令牌时,我将其放入请求 header 中,如下所示:

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

ClientContext.ExecutingWebRequest订阅方法中:

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

这是由

context.ExecuteQuery();

远程服务器返回错误:(401) 未经授权。 或远程服务器返回错误:(403) 禁止访问。

如何建立连接? 我想避免使用仅应用程序注册,我想使用 Azure AD MFA(交互式)方法进行身份验证。请注意,我拥有所需的所有权限,并且我是 Azure AD 的管理员,其中加入了 SharePoint,以及SharePoint 服务器本身。 我通过浏览器进行身份验证就好了。

到目前为止,我已经尝试了多种方法:

  • 我尝试创建一个单独的请求,在其中我将之前获取的 accessToken 转发为 Authorization: Bearer token

  • 我尝试从身份验证连接 window 读取 FedAuth,因此我可以在我的 HTTP 请求中转发它,但没有成功

  • 我尝试使用 WebBrowser C# class 创建一个“Web 浏览器”,并读取浏览器级别的 cookies,如下所示: cookieContainer = webBrowser1.Document.Cookie; 但我没有成功。

我希望通过 Azure AD 进行身份验证,然后连接到 SharePoint 以查询它

要解决错误“远程服务器返回错误:(401) 未经授权”,请尝试检查以下内容:

  • 查看你的URL是否正确:

SharePoint在线URL必须始终以HTTPS开头。

$SiteURL`  `=` `"https://crescent.sharepoint.com/sites/marketing"`
  • 检查您是否拥有该站点的正确权限:

检查您是否有足够的权限,以及您是否能够在浏览器中打开该网站。 确保拥有 SharePoint 在线管理员角色。

  • 检查Legacy认证协议是否启用:

如果未启用,请确保在您的租户中启用旧版身份验证协议。

参考SharePoint 在线:修复PowerShell中的“远程服务器返回错误(401)未授权”错误 - SharePoint日记

要解决错误“远程服务器返回错误:(403) 禁止访问。”,请尝试检查以下内容:

  • 确保您是否提供了正确的 URL 和凭据。

  • 请确认您是否安装了最新版本的SharePoint在线客户端组件SDK。

  • 尝试明确地将自己添加到网站

  • 检查您站点的锁定状态,如果锁定则解锁。

  • 请检查您的租户中是否启用了任何条件访问策略。

  • 如果您尝试连接到 Tenant Admin 站点,请确保 Tenant Admin URL 如下所示:

     https://YourDomain-admin.sharepoint.com

参考SharePoint 在线:修复“远程服务器返回错误:(403)禁止访问。” PowerShell - SharePoint 日记中的错误

我找到了解决方案。

每当浏览器浏览新页面时,我基本上遍历所有 cookies 并解析所有 cookies 直到我获得 fedAuth cookie:

  1. 我从 System.Windows.Forms.WebBrowser 创建了一个 web 浏览器

  2. NavigatedWebBrowserNavigatedEventHandler中,我执行以下操作:

    如果 (webBrowser1.Url.AbsoluteUri == "about:blank") { 返回; }

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

    if (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.UpdateConfiguration(); 这个。关闭(); } }

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 class 看起来像这样:

[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# web 浏览器,使用 MFA 通过 web 对用户进行身份验证,然后在我们获取身份验证 cookie 时关闭浏览器,以便我们可以继续处理 HTTP 对 Sharepoint 服务器的请求。

来源: https://github.com/OceanAirdrop/SharePointOnlineGetFedAuthAndRtfaCookie

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM