MSAL AD令牌对SharePoint Online CSOM无效

时间:2019-02-19 16:53:57

标签: sharepoint-online msal

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

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

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

有人能够指定必要的范围,并利用具有来自MSAL的承载授权的OAuth令牌来访问SharePoint Online吗?

2 个答案:

答案 0 :(得分:7)

据我所知,您无法通过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"

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

(它也可以与New-SelfSignedCertificate命令一起使用)

注册证书

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

image

配置应用程序API权限

之后,您必须授权SharePoint API:

image

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

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

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

要使其正常工作,您必须分三步操作(我已对其进行了简化,但最好通过一些try / catch将操作分成方法)

获取Pfx证书

对于此步骤,我强烈建议使用KeyVault(请参见文章底部的链接)

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

获取令牌

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;

测试您的连接

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();
*/

如果我什么都没错过,您应该获得一些Web /用户信息! ?

希望有帮助。

编辑(2020年11月14日):即使在我的API权限屏幕截图中,如果您尝试更新应用程序权限“ User.ReadWrite.All”,我也会添加该权限用户个人资料,它将无法使用。若要解决此问题,您必须将AAD应用程序注册为仅旧版SharePoint App主体(客户端ID /机密)。更多信息here

感谢@laurakokkarinen@mmsharepoint的文章对我(herehere的确有帮助)

答案 1 :(得分:0)

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

var clientContext = new ClientContext(siteUrl);
clientContext.Credentials = new SharePointOnlineCredentials(userName, securedPassword);

您已完成CSOM API的使用。

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

enter image description here

如果此字段包含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();

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

当您解码新的喷射令牌时,它应该像这样

enter image description here