基于Teams AI库的操作型消息扩展:如何启用SSO并获取有效Graph API访问令牌
基于Teams AI库的操作型消息扩展:如何启用SSO并获取有效Graph API访问令牌
看起来你已经走在正确的路上了!我来帮你完善代码逻辑,实现「未授权时引导用户跳转到 consent 对话框,已授权则打开任务自适应卡片」的需求,同时顺利拿到Graph API的访问令牌。
第一步:完善SSO基础配置
首先确保你的MSAL和认证选项配置完整,这里要注意signInLink是机器人接收Teams授权回调的HTTPS端点,必须提前在你的机器人服务中配置好:
// 初始化MSAL客户端 IConfidentialClientApplication msal = ConfidentialClientApplicationBuilder.Create(config.AppId) .WithClientSecret(config.AppPassword) .WithTenantId(config.AppTenantId) .WithLegacyCacheCompatibility(false) .Build(); // 配置SSO的回调地址(替换成你的机器人域名对应的auth端点) string signInLink = $"https://{config.BotDomain}/api/auth"; // 配置Graph API的认证方案,这里可根据需求添加权限范围 AuthenticationOptions<AppState> authOptions = new(); authOptions.AddAuthentication("graph", new TeamsSsoSettings( scopes: new string[] { "User.Read", "Mail.Read" }, // 按需添加Graph权限 signInLink: signInLink, msalApp: msal )); // 构建完整的应用实例 var app = new ApplicationBuilder<AppState>() .WithAIOptions(new(actionPlanner)) .WithStorage(storage) .WithLoggerFactory(loggerFactory) .WithTurnStateFactory(() => new AppState()) .WithAuthentication(authOptions) .Build();
第二步:添加授权回调端点
你需要在机器人的控制器中添加一个api/auth的路由,用来处理Teams的SSO授权回调:
[Route("api/auth")] [ApiController] public class AuthController : ControllerBase { private readonly IAuthenticationService _authService; public AuthController(IAuthenticationService authService) { _authService = authService; } [HttpGet] public async Task<IActionResult> SignInAsync([FromQuery] string state) { // 交由Teams AI库处理授权逻辑 var result = await _authService.HandleSignInAsync(HttpContext, "graph", state); return result; } }
第三步:处理消息扩展的Action逻辑
接下来就是核心的消息扩展处理逻辑——判断用户授权状态,返回对应的响应:
// 注册你消息扩展中定义的Action处理函数(替换成你的Action ID) app.AddMessageExtensionHandler( "your_action_id", async (turnContext, state, ct) => { // 获取认证服务实例 var authService = turnContext.TurnState.Get<IAuthenticationService>(); if (authService == null) { throw new InvalidOperationException("认证服务未初始化"); } try { // 尝试获取用户的Graph API访问令牌 var tokenResult = await authService.GetUserTokenAsync( turnContext, "graph", // 对应之前配置的认证方案名称 ct: ct ); if (tokenResult.Succeeded && !string.IsNullOrEmpty(tokenResult.Token)) { // ✅ 用户已授权,拿到令牌后调用Graph API var graphClient = new GraphServiceClient( new DelegateAuthenticationProvider(request => { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenResult.Token); return Task.CompletedTask; }) ); // 示例:调用Graph获取当前用户信息 var user = await graphClient.Me.GetAsync(cancellationToken: ct); // 构建并返回任务自适应卡片 return new TaskModuleResponse { Task = new TaskModuleContinueResponse { Type = "continue", Value = new TaskModuleTaskInfo { Title = $"欢迎回来,{user.DisplayName}!", Width = "medium", Height = "medium", Card = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0)) { Body = new List<AdaptiveElement> { new AdaptiveTextBlock { Text = "您已完成授权,可以继续操作", Size = AdaptiveTextSize.Medium }, new AdaptiveTextBlock { Text = $"邮箱:{user.Mail}" } } } } } }; } else { // ❌ 用户未授权,返回登录引导,让Teams弹出consent对话框 return new TaskModuleResponse { Task = new TaskModuleSignInResponse { Type = "signin", Value = new TaskModuleSignInResponseValue { SignInLink = signInLink } } }; } } catch (Exception ex) { // 记录异常日志,方便排查问题 loggerFactory.CreateLogger("MessageExtensionHandler").LogError(ex, "处理消息扩展请求时发生错误"); throw; } } );
几个关键注意点
- 权限配置:务必在Azure AD应用注册中添加你需要的Graph API权限(比如
User.Read),如果是租户级权限,还需要管理员提前授予同意。 - 令牌管理:Teams AI库会自动帮你处理令牌的缓存、刷新逻辑,不需要手动维护令牌生命周期。
- HTTPS要求:
signInLink必须是HTTPS地址,Teams不允许HTTP的回调端点。
这样配置后,用户触发消息扩展的Action时,系统会自动判断授权状态:未授权则弹出consent对话框,授权完成后自动回到任务卡片;已授权则直接加载卡片并调用Graph API。
备注:内容来源于stack exchange,提问作者YonF
相关产品推荐
相关产品推荐

