Bot Framework中Skype for Business渠道免Signin-Card获取用户Token咨询
无需Signin Card实现Skype for Business Bot访问Microsoft Graph的解决方案
没问题,针对你用C#开发的Skype for Business Bot需要访问用户邮件及Microsoft Graph内容,且不想用Signin Card的需求,我整理了几个可行的技术思路,结合实际代码示例帮你落地:
核心思路:利用Azure AD的On-Behalf-Of(OBO)流程
由于用户已完成预认证,我们可以借助Bot的服务主体身份,通过OBO流程静默获取用户的Microsoft Graph访问令牌,无需用户再次登录或点击Signin Card。
步骤1:配置Azure AD应用权限
首先确保你的Bot在Azure AD中的应用注册满足以下要求:
- 添加Delegated类型的Microsoft Graph权限(比如
Mail.Read、Calendars.Read等你需要的权限) - 由租户管理员完成权限同意(如果是面向整个租户的Bot),或者用户已预先单独同意过这些权限
步骤2:在Bot代码中实现OBO令牌获取
使用Microsoft.Identity.Client库(MSAL.NET)来完成令牌交换,核心代码示例如下:
using Microsoft.Identity.Client; using Microsoft.Graph; using System.Net.Http.Headers; // 初始化Confidential Client(Bot的服务主体) var confidentialClient = ConfidentialClientApplicationBuilder .Create("<你的Bot应用Client ID>") .WithClientSecret("<你的Bot应用Client Secret>") .WithAuthority(new Uri("https://login.microsoftonline.com/<你的租户ID>")) .Build(); // 从Skype for Business的活动中获取用户身份标识(比如UPN或Azure AD对象ID) var userUpn = turnContext.Activity.From.Name; // 注意:需确保Skype for Business传递了正确的用户UPN // 构造用户断言(这里需要Bot先获取自身的令牌,或者从活动中提取用户的身份令牌) // 如果你能从Bot活动中获取到用户的ID Token,直接用它作为UserAssertion的参数 var userAssertion = new UserAssertion("<用户的ID Token>", "urn:ietf:params:oauth:grant-type:jwt-bearer"); // 调用OBO流程获取用户的Graph访问令牌 var authResult = await confidentialClient.AcquireTokenOnBehalfOf( new[] { "https://graph.microsoft.com/Mail.Read" }, // 你需要的Graph权限范围 userAssertion) .ExecuteAsync(); // 使用令牌初始化Graph Client并调用接口 var graphClient = new GraphServiceClient( new DelegateAuthenticationProvider((requestMessage) => { requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken); return Task.CompletedTask; })); // 示例:获取用户的邮件列表 var userMessages = await graphClient.Me.Messages.Request().Top(10).GetAsync();
补充思路:预先配置应用级权限(适用于批量访问场景)
如果你的Bot需要以自身身份访问多个用户的Graph内容(而非代表单个用户),可以配置Application类型的Graph权限,这种方式不需要用户授权,直接用Bot的服务主体令牌访问:
// 初始化Confidential Client var confidentialClient = ConfidentialClientApplicationBuilder .Create("<Bot Client ID>") .WithClientSecret("<Bot Client Secret>") .WithAuthority(new Uri("https://login.microsoftonline.com/<租户ID>")) .Build(); // 获取应用级令牌 var authResult = await confidentialClient.AcquireTokenForClient( new[] { "https://graph.microsoft.com/.default" }) // 应用级权限使用.default范围 .ExecuteAsync(); // 调用Graph API(需使用用户ID而非Me) var userMessages = await graphClient.Users["<用户Azure AD对象ID>"].Messages.Request().Top(10).GetAsync();
关键注意事项
- 令牌缓存:务必实现令牌缓存机制,避免每次请求都重新获取令牌,提升性能并减少Azure AD的请求次数
- 权限范围:严格控制所需的Graph权限,遵循最小权限原则,避免过度授权
- Skype for Business身份传递:确保Skype for Business渠道正确传递用户的身份信息(如UPN),如果无法直接获取,可通过Bot Framework的
GetUserTokenAsync方法结合预授权配置静默获取
内容的提问来源于stack exchange,提问作者vishnu mohan
相关产品推荐
相关产品推荐

