能否基于用户UPN实现无密码令牌认证并控制MS Graph搜索权限?
解决方案:基于UPN无密码获取用户令牌并限制MS Search API返回结果
核心问题分析
你当前使用应用权限调用MS Graph Search API,所以返回整个租户的SharePoint数据;要返回用户可访问的内容,必须以用户身份上下文调用API,同时需要实现无弹窗、无密码获取对应令牌。
可行解决方案
1. 替换ADAL为MSAL库
Microsoft.IdentityModel.Clients.ActiveDirectory(ADAL)已被弃用,建议改用Microsoft.Identity.Client(MSAL),它支持更符合需求的现代认证流程,且官方维护更活跃。
2. 采用On-Behalf-Of (OBO) 认证流程
这是Web应用场景下的最优方案:
- 前提:Web应用前端通过静默登录(比如MSAL.js的
acquireTokenSilent方法)获取用户的ID令牌,将该令牌传递给后端。 - 后端利用这个用户令牌,以用户身份获取Graph API的访问令牌,全程无需用户再次输入密码或触发登录弹窗。
- 代码示例(C#):
using Microsoft.Identity.Client; using System.Net.Http.Headers; // 定义需要的Graph API权限 var scopes = new[] { "https://graph.microsoft.com/Search.Read" }; // 从前端请求中获取用户的ID令牌 var userAssertionToken = "前端传递的用户ID令牌"; // 初始化MSAL客户端 var confidentialClient = ConfidentialClientApplicationBuilder .Create("你的Azure AD应用ID") .WithClientSecret("你的应用密钥") .WithTenantId("租户ID") .Build(); // 获取代表用户的Graph访问令牌 var tokenResult = await confidentialClient.AcquireTokenOnBehalfOf(scopes, new UserAssertion(userAssertionToken)) .ExecuteAsync(); // 使用该令牌调用MS Search API,将返回用户可访问的站点 var searchRequest = new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/v1.0/search/query"); searchRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenResult.AccessToken); // 构造搜索请求体(如指定搜索类型为站点等)...
3. 用户模拟的应用权限(仅限特定场景)
如果无法获取前端传递的用户令牌,可申请Directory.AccessAsUser.All应用权限(需租户管理员同意),该权限允许应用模拟指定UPN的用户身份调用API:
- 代码示例(C#):
using Microsoft.Identity.Client; using System.Net.Http.Headers; var scopes = new[] { "https://graph.microsoft.com/.default" }; var targetUpn = "目标用户的UPN"; var confidentialClient = ConfidentialClientApplicationBuilder .Create("你的Azure AD应用ID") .WithClientSecret("你的应用密钥") .WithTenantId("租户ID") .Build(); // 获取模拟用户的访问令牌 var tokenResult = await confidentialClient.AcquireTokenForClient(scopes) .WithExtraQueryParameters(new Dictionary<string, string> { { "upn", targetUpn } }) .ExecuteAsync(); // 用该令牌调用Search API,将返回该用户可访问的内容 var searchRequest = new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/v1.0/search/query"); searchRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenResult.AccessToken);
注意:此权限风险较高,仅适合后台自动化任务等场景,需严格控制应用权限范围,避免滥用。
4. 验证API调用上下文
无论采用哪种方案,必须确保调用MS Search API时使用的是用户上下文令牌——应用权限令牌会绕过用户权限校验,直接返回全租户数据,这是你当前问题的核心原因。
内容的提问来源于stack exchange,提问作者손동진
相关产品推荐
相关产品推荐

