MSAL AD 令牌对 SharePoint Online CSOM 无效

AWe*_*ber 5 sharepoint-online azure-ad-msal

我能够在桌面 .Net 项目中通过 MSAL 检索和使用访问令牌。我可以成功检索令牌,并且它们在我的 Graph 调用中有效。

但是,尝试将访问令牌与 SharePoint Online CSOM 一起使用会导致 401:未经授权。这类似于使用 msal throws 401 访问共享点 REST api(除了我使用的是 C# 和最新的 CSOM)。

据我了解,MSFT 正试图将开发人员从 ADAL 转移到 MSAL,但令牌似乎存在一些兼容性问题。

有没有人能够指定必要的范围并利用来自 MSAL 的持有者授权的 OAuth 令牌来访问 SharePoint Online?

mic*_*lot 10

据我所知,您不能通过 AAD 使用客户端/秘密令牌请求 SharePoint REST API。但它适用于证书。下面一步一步来:

由于我面临同样的问题,我将在此处发布我如何通过带有 MSAL(OAuth v2 和 AAD v2 端点)的 AAD 应用程序连接到 SharePoint API。它在 C# 中。

首先,我只获得了证书(据我所知,客户端/秘密方法不起作用)。

创建证书

出于测试目的,我创建了一个带有“ New-PnPAzureCertificate ”的自签名证书,如下所示:

$secPassword = ConvertTo-SecureString -String "MyPassword" -AsPlainText -Force
$cert = New-PnPAzureCertificate -OutCert "CertSPUser.cer" -OutPfx "CertSPUser.pfx" -ValidYears 10  -CertificatePassword $secPassword -CommonName "CertSPUser" -Country "FR" -State "France"
Run Code Online (Sandbox Code Playgroud)

-Country-State参数对测试无关紧要)

(它也适用于New-SelfSignedCertificate命令)

注册证书

然后,您必须在 AAD 应用程序(“.cer”文件)中上传证书:

图片

配置应用程序 API 权限

之后,您必须授权 SharePoint API:

图片

尝试通过 Daemon App (C#) 访问

NuGet 包(希望我什么都没有忘记)

  • Microsoft.SharePointOnline.CSOM
  • Microsoft.Identity.Client

为了使事情工作,你必须分 3 个步骤(我已经简化了它,但你最好通过一些 try/catch 将操作分成方法)

获取 Pfx 证书

对于这一步,我强烈建议使用 KeyVault(请参阅帖子底部的链接)

string certPath = System.IO.Path.GetFullPath(@"C:\PathTo\CertSPUser.pfx");
X509Certificate2 certificate = new X509Certificate2(certPath, "MyPassword", X509KeyStorageFlags.MachineKeySet);
Run Code Online (Sandbox Code Playgroud)

获取令牌

string tenantId = "yourTenant.onmicrosoft.com" // Or "TenantId"
string applicationId = "IdOfYourAADApp"
IConfidentialClientApplication confApp = ConfidentialClientApplicationBuilder.Create(applicationId)
.WithAuthority($"https://login.microsoftonline.com/{tenantId}")
.WithCertificate(certificate)
.Build();

string sharePointUrl = "https://yourSharePoint.sharepoint.com" // Or "https://yourSharePoint-admin.sharepoint.com" if you want to access the User Profile REST API
var scopes = new[] { $"{sharePointUrl}/.default" };
var authenticationResult = await confApp.AcquireTokenForClient(scopes).ExecuteAsync();
string token = authenticationResult.AccessToken;
Run Code Online (Sandbox Code Playgroud)

测试您的连接

ClientContext ctx = new ClientContext(sharePointUrl);
ctx.ExecutingWebRequest += (s, e) =>
{
      e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + token;
};

Web web = ctx.Web;
ctx.Load(web);
ctx.Load(web);
ctx.ExecuteQuery();

// OR if you connect to User Profile ("yourSharePoint-admin.sharepoint.com")
/* 
PeopleManager peopleManager = new PeopleManager(ctx);
var personProperties = peopleManager.GetUserProfileProperties("i:0#.f|membership|employee.mail@tenant.onmicrosoft.com");
ctx.ExecuteQuery();
*/
Run Code Online (Sandbox Code Playgroud)

如果我没有错过任何东西,您应该会得到一些网络/用户信息!

希望它有帮助。

编辑(2020 年 11 月 14 日):即使在 API 权限的屏幕截图中我添加了应用程序权限“User.ReadWrite.All”,如果您尝试更新用户配置文件,它也不会起作用。要解决此问题,您必须将 AAD 应用程序注册为旧版 SharePoint App-Only 主体(客户端 ID/机密)。更多信息在这里

感谢@laurakokkarinen@mmsharepoint的文章对我有很大帮助(这里这里


Ser*_*hon 6

不确定您为什么直接使用 MSAL 来访问 SharePoint Online API。最简单的方法应该是使用Microsoft.SharePointOnline.CSOM

var clientContext = new ClientContext(siteUrl);
clientContext.Credentials = new SharePointOnlineCredentials(userName, securedPassword);
Run Code Online (Sandbox Code Playgroud)

您就完成了 CSOM API。

但我认为 MSAL 也应该是可能的。请记住,您获得的令牌是为某些资源授予的。将您的令牌解析复制到http://jwt.ms/并查看aud

在此处输入图片说明

如果此字段包含https://graph.microsoft.com它就对您无效https://yourtenant.sharepoint.com,您需要不同的!

您应该能够使用Microsoft.Identity.Client请求正确的令牌

var authority = $"https://login.microsoftonline.com/{tenantId}";
var app = ConfidentialClientApplicationBuilder.Create(clientId)
    .WithClientSecret(clientSecret)
    .WithAuthority(new Uri(authority))
    .Build();

var scopes = new[] { "https://yourtenant.sharepoint.com/.default" };
var authenticationResult = await app.AcquireTokenForClient(scopes)
    .ExecuteAsync();
Run Code Online (Sandbox Code Playgroud)

因此authenticationResult.AccessToken应包含对 SharePoint Online REST API 有效的访问令牌。(https://yourtenant.sharepoint.com/.default意味着您请求为您的 Azure AD 应用程序配置的所有范围)

当您解码新的 jet 令牌时,它应该如下所示

在此处输入图片说明

  • 请参阅 @michaelmaillot 答案:使用客户端密钥时您会获得 jwt 令牌,但当您尝试使用它时,SharePoint REST API 返回“401 未授权”。使用证书代替可以正常工作。不确定这是否记录在某处,但这当然很烦人。 (2认同)