Azure AD登录后调用Microsoft Graph API for Teams遇令牌及权限问题求助
问题解决:Azure AD登录后调用Microsoft Graph Teams API的令牌错误与配置方案
问题概述
用户通过Azure AD登录应用后,尝试调用Microsoft Graph API for Teams发送消息到频道时,先后遇到两个错误:
- 「Invalid Audience」:获取的access_token受众不符合Graph API要求
- 「Tokens issued for the 'Single-Page Application' client-type may only be redeemed via cross-origin requests」:应用客户端类型与授权流程不匹配
同时疑惑是否需要配置委派权限及具体权限要求。
错误原因分析
- Invalid Audience错误:初始配置中
Resource = clientId,导致获取的access_token受众是自身应用,而非Microsoft Graph(受众应为https://graph.microsoft.com),无法用于调用Graph API。 - 客户端类型不匹配错误:Azure AD应用注册时客户端类型设为「Single-Page Application (SPA)」,但代码使用的是服务器端的Authorization Code Flow(在服务器端兑换授权码),而SPA类型应用要求必须通过跨域请求(如PKCE流程)兑换令牌,禁止服务器端直接兑换。
正确配置方案
一、Azure AD应用注册调整
- 修改客户端类型:将应用注册的客户端类型改为Web(而非SPA),适配服务器端的Authorization Code Flow。
- 添加委派权限:因为是以登录用户的身份调用Graph API,必须配置委派权限,需添加:
Teams.SendChannelMessage:允许用户发送消息到Teams频道openid、profile:基础身份验证权限offline_access:允许获取刷新令牌,实现长期访问
- 完成权限同意:如果是租户级应用,需由管理员授予管理员同意;如果是多租户应用,可引导用户完成用户同意。
- 配置重定向URI:确保重定向URI为Web类型,与代码中
DetermineRedirectUri返回的地址一致。
二、代码配置修正
修正后的认证配置代码
public void ConfigureAuth(IAppBuilder app) { app.UseSwaggerUi3(typeof(CoreErrorController).Assembly, settings => { settings.GeneratorSettings.Title = "Sample API"; }); app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseCookieAuthentication(new CookieAuthenticationOptions() { CookieName = "azureADCookie", ExpireTimeSpan = TimeSpan.FromMinutes(60) }); app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions() { ClientId = clientId, Authority = authority, // 格式应为https://login.microsoftonline.com/{tenant-id} // 包含Graph权限、基础身份权限和离线访问权限 Scope = "openid profile offline_access Teams.SendChannelMessage", Resource = "https://graph.microsoft.com", // 指定受众为Microsoft Graph(v1.0端点需配置) ResponseType = OpenIdConnectResponseType.Code, // 使用Authorization Code Flow SaveTokens = true, // 保存令牌到Cookie RedeemCode = true, ClientSecret = clientSecret, // 需添加应用注册的客户端密钥,Web应用必须配置 TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = false }, Notifications = new OpenIdConnectAuthenticationNotifications() { RedirectToIdentityProvider = (o) => { o.ProtocolMessage.RedirectUri = DetermineRedirectUri(o.Request).ToLower(); return Task.CompletedTask; }, AuthorizationCodeReceived = async (o) => { o.TokenEndpointRequest.RedirectUri = DetermineRedirectUri(o.Request).ToLower(); // 手动获取Graph令牌,确保令牌正确 var confidentialClient = ConfidentialClientApplicationBuilder .Create(clientId) .WithClientSecret(clientSecret) .WithAuthority(authority) .WithRedirectUri(o.TokenEndpointRequest.RedirectUri) .Build(); var result = await confidentialClient.AcquireTokenByAuthorizationCode( new[] { "Teams.SendChannelMessage", "openid", "profile" }, o.Code).ExecuteAsync(); // 将令牌保存到认证属性中 o.AuthenticationTicket.Properties.Dictionary["access_token"] = result.AccessToken; o.AuthenticationTicket.Properties.Dictionary["refresh_token"] = result.RefreshToken; return Task.CompletedTask; }, AuthenticationFailed = OnAuthenticationFailed } }); }
获取access_token的修正代码
// 从Owin上下文获取保存的access_token var authResult = HttpContext.Current.GetOwinContext().Authentication.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationType).Result; var accessToken = authResult.Properties.Dictionary["access_token"];
关键说明
- 必须确保应用注册的客户端类型与授权流程匹配:Web应用使用Authorization Code Flow(需客户端密钥),SPA使用PKCE流程。
- 调用Graph API时,access_token的受众必须是
https://graph.microsoft.com,否则会出现Invalid Audience错误。 - 委派权限是用户身份调用Graph的必要条件,应用权限适用于后台服务(无需用户登录)的场景。
内容的提问来源于stack exchange,提问作者Raghu Ramakrishna
相关产品推荐
相关产品推荐

