使用Azure AD应用程序编程访问SharePoint文件时遇未授权问题
已创建Azure AD应用程序,获取了用户令牌,但访问任意SharePoint站点文件时始终返回**未授权(Unauthorized)**错误。浏览器直接访问文件URL可正常打开,但代码中使用委派用户令牌无法访问。
下载文件代码
using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", userToken); var respons = await client.GetAsync(url); if (respons.StatusCode == System.Net.HttpStatusCode.OK) { var downloadStream = await respons.Content.ReadAsStreamAsync(); } else { }
尝试的SharePoint REST API请求方式
string webUrl = "xxx"; string fileUrl = "yyy"; var requestUrl = String.Format("{0}/_api/web/getfilebyserverrelativeurl('{1}')/$value", webUrl, fileUrl);
使用的授权请求参数
- 用于Files权限的授权请求:
https://login.microsoftonline.com/tenantName/oauth2/v2.0/authorize?client_id=theclientID&response_type=code&redirect_uri=http%3A%2F%2Flocalhost&response_mode=query&scope=Files.ReadWrite.All&prompt=consent - 用于Sites权限的授权请求(尝试访问共享OneDrive/SharePoint文件):
https://login.microsoftonline.com/tenantName/oauth2/v2.0/authorize?client_id=theclientID&response_type=code&redirect_uri=http%3A%2F%2Flocalhost&response_mode=query&scope=Sites.ReadWrite.All&prompt=consent
获取令牌的代码
private async Task<string> GetTokenForUserAsync() { _clientId ="xxx"; _clientSecret ="yyy"; _domainName ="zzz"; string graphUrl = global::Utils.Tools.AzureURL.GetGraphUrl(AzureCloudInstance.AzurePublic); string loginUrl = global::Utils.Tools.AzureURL.GetLoginUrl(AzureCloudInstance.AzurePublic); loginUrl = string.Format("{0}/{1}", loginUrl, _domainName); string redirectUri = "https://myapp.azurewebsites.net"; IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(_clientId) .WithClientSecret(_clientSecret) .WithAuthority(loginUrl) .WithRedirectUri(redirectUri) .Build(); string[] scopes = new string[] { graphUrl + "/.default" }; //string[] scopes = new string[] { graphUrl + "/Files.Read.All" }; Microsoft.Identity.Client.AuthenticationResult result = null; result = await app.AcquireTokenForClient(scopes).ExecuteAsync(); return result.AccessToken; }
核心问题:获取的是应用权限令牌,而非委派用户令牌
你当前用AcquireTokenForClient获取的是应用权限令牌,这种令牌基于应用本身的权限,不会模拟用户的身份和权限。而你需要的是委派用户权限令牌,才能以用户身份访问其有权限的SharePoint文件。
具体修正步骤
切换令牌获取方式
替换AcquireTokenForClient为适合委派权限的方法,比如授权码流程的AcquireTokenByAuthorizationCode:// 假设已通过授权码流程获取到authorizationCode var result = await app.AcquireTokenByAuthorizationCode( new string[] { "Files.ReadWrite.All", "Sites.ReadWrite.All" }, authorizationCode) .ExecuteAsync();注意:授权请求中的
redirect_uri必须和代码里的redirectUri保持一致(当前授权请求用的是http://localhost,代码里是https://myapp.azurewebsites.net,需统一)。统一Scope配置
- 委派权限的Scope无需加
graphUrl + "/"前缀,直接使用权限名称,比如"Files.ReadWrite.All"、"Sites.ReadWrite.All"。 - 授权请求的Scope必须和令牌获取时的Scope完全一致,避免权限不匹配。
- 委派权限的Scope无需加
验证应用权限配置
在Azure AD应用的「API权限」中,确认已添加对应的委派权限(Files.ReadWrite.All、Sites.ReadWrite.All),且已完成管理员同意(如果是租户级权限)。REST API请求校验
调用SharePoint REST API时,确保webUrl是正确的站点URL,fileUrl为服务器相对路径(比如/sites/TestSite/Documents/TestFile.docx);更推荐使用Microsoft Graph API访问文件,兼容性更好。
内容的提问来源于stack exchange,提问作者CloudAnywhere

