Azure C#无弹窗获取用户令牌并查询用户组的方案咨询
解决方案说明
为什么之前调用接口报错
你用ConfidentialClientApplicationBuilder获取的是应用权限令牌——这类令牌代表应用本身执行操作,没有绑定具体用户上下文。而/me接口依赖当前用户的上下文才能识别要查询的对象,所以用应用权限令牌调用必然返回错误。
可行方案分两种场景
场景1:查询特定已知用户的组信息(无需用户交互)
如果你的WebAPI只需查询某个固定用户的组,直接用应用权限流即可,调整接口调用路径:
- 在Azure AD应用注册中添加应用权限(比如
Group.Read.All),并联系租户管理员完成权限同意 - 调用Graph API的
users/{userPrincipalName}/memberOf接口(替换{userPrincipalName}为目标用户的邮箱或UPN) - C#代码示例:
using Microsoft.Identity.Client; using System.Net.Http.Headers; using System.Text.Json; var tenantId = "你的tenant_id"; var clientId = "你的client_id"; var clientSecret = "你的client_secret"; var targetUserUpn = "目标用户的UPN(比如user@domain.com)"; // 构建客户端并获取应用权限令牌 var app = ConfidentialClientApplicationBuilder .Create(clientId) .WithClientSecret(clientSecret) .WithTenantId(tenantId) .Build(); var scopes = new[] { "https://graph.microsoft.com/.default" }; var result = await app.AcquireTokenForClient(scopes).ExecuteAsync(); // 调用Graph API查询用户组 using var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken); var response = await httpClient.GetAsync($"https://graph.microsoft.com/v1.0/users/{targetUserUpn}/memberOf"); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var groups = JsonSerializer.Deserialize<JsonElement>(content); // 处理返回的组数据
场景2:代表当前访问WebAPI的用户查询其自身组信息
如果WebAPI需要处理已登录用户的请求,用On-Behalf-Of(OBO)流:
- 前端先通过授权码流获取用户的访问令牌(这一步的弹窗在前端完成,后端WebAPI无弹窗)
- 前端将令牌传给你的WebAPI,WebAPI用OBO流换取针对Graph API的令牌
- 调用
/me/memberOf接口查询用户自身组 - C#代码示例(WebAPI中的逻辑):
using Microsoft.Identity.Client; using System.Net.Http.Headers; using System.Text.Json; var tenantId = "你的tenant_id"; var clientId = "你的client_id"; var clientSecret = "你的client_secret"; // 从请求头中获取前端传入的用户令牌 var userToken = Request.Headers.Authorization.Parameter; // 构建客户端并执行OBO流 var app = ConfidentialClientApplicationBuilder .Create(clientId) .WithClientSecret(clientSecret) .WithTenantId(tenantId) .Build(); var scopes = new[] { "https://graph.microsoft.com/Group.Read.All" }; var result = await app.AcquireTokenOnBehalfOf(scopes, new UserAssertion(userToken)).ExecuteAsync(); // 调用Graph API查询当前用户组 using var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken); var response = await httpClient.GetAsync("https://graph.microsoft.com/v1.0/me/memberOf"); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); var groups = JsonSerializer.Deserialize<JsonElement>(content); // 处理返回的组数据
注意事项
- 应用权限需要租户管理员同意,委派权限若为“管理员同意”类型也需管理员操作,否则普通用户授权即可
- 避免使用资源所有者密码凭证(ROPC)流,该方式安全性低,Microsoft不推荐用于生产环境
内容的提问来源于stack exchange,提问作者Baz
相关产品推荐
相关产品推荐

