ASP.NET Core页面兼容Azure AD与本地用户并调用Microsoft Graph的问题
解决方案
问题分析
核心问题在于:当页面同时允许Cookie(本地用户)和OpenIdConnect(Azure AD用户)两种认证Scheme时,Microsoft Identity Web无法自动确定使用哪个Scheme获取Azure AD令牌,导致调用Graph时抛出IDW10503异常;同时之前的双[Authorize]配置要求用户同时通过两种认证,不符合"任一认证通过即可访问"的需求。
关键修改点
- 调整页面授权规则:将双
[Authorize]改为单个[Authorize]并通过逗号分隔两种Scheme,实现"任一认证通过即可访问"的逻辑。 - 明确指定Graph令牌的认证Scheme:调用Graph时,强制使用
OpenIdConnectDefaults.AuthenticationScheme获取令牌,避免自动推断错误。 - 正确识别Azure AD用户:通过用户身份的
AuthenticationScheme判断是否为Azure AD认证用户。
完整代码修改
1. 认证配置(添加Graph服务支持)
var builder = WebApplication.CreateBuilder(args); // 配置认证,默认Scheme为Cookie builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddNegotiate() // 本地用户名密码认证 .AddMicrosoftIdentityWebApp(builder.Configuration, "Authentication:AzureAD") // 添加Graph服务支持,配置所需权限 .EnableTokenAcquisitionToCallDownstreamApi(new[] { "Mail.Read" }) .AddMicrosoftGraph(builder.Configuration.GetSection("Graph")) .AddInMemoryTokenCaches(); builder.Services.AddRazorPages() .AddMicrosoftIdentityUI(); var app = builder.Build(); app.UseSession(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapRazorPages(); app.Run();
2. Razor页面代码调整
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.Identity.Web; using Microsoft.Graph; // 允许Cookie或OpenIdConnect认证的用户访问页面 [Authorize(AuthenticationSchemes = $"{CookieAuthenticationDefaults.AuthenticationScheme},{OpenIdConnectDefaults.AuthenticationScheme}")] public class GraphCMSModel : PageModel { private readonly ITokenAcquisition _tokenAcquisition; private readonly GraphServiceClient _graphClient; public string Message { get; set; } = string.Empty; public GraphCMSModel(ITokenAcquisition tokenAcquisition, GraphServiceClient graphClient) { _tokenAcquisition = tokenAcquisition; _graphClient = graphClient; } public async Task OnGetAsync() { // 判断当前用户是否通过Azure AD认证 bool isAzureAdUser = User.Identity?.AuthenticationScheme == OpenIdConnectDefaults.AuthenticationScheme; if (isAzureAdUser) { try { // 明确指定使用OpenIdConnect Scheme获取Graph访问令牌 var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync( new[] { "Mail.Read" }, authenticationScheme: OpenIdConnectDefaults.AuthenticationScheme); // 使用令牌调用Graph获取未读邮件 var unreadMessages = await _graphClient.Me.MailFolders["Inbox"].Messages .Request() .Filter("isRead ne true") .WithBearerToken(accessToken) .GetAsync(); Message = $"你有 {unreadMessages.Count} 封未读邮件"; } catch (Exception ex) { Message = $"获取邮件信息失败: {ex.Message}"; } } else { Message = "暂无Graph相关信息"; } } }
补充说明
确保appsettings.json中已配置Azure AD和Graph的相关参数:
"Authentication": { "AzureAD": { "Instance": "https://login.microsoftonline.com/", "Domain": "your-domain.onmicrosoft.com", "TenantId": "your-tenant-id", "ClientId": "your-client-id", "CallbackPath": "/signin-oidc" } }, "Graph": { "BaseUrl": "https://graph.microsoft.com/v1.0", "Scopes": "Mail.Read" }
内容的提问来源于stack exchange,提问作者Stefano
相关产品推荐
相关产品推荐

