ASP.NET MVC中Azure AD组授权异常:已在组内仍遭访问拒绝
ASP.NET MVC Azure AD组授权访问被拒绝问题
我在ASP.NET MVC控制器的特定视图页面上使用[Authorize(Policy = "it")]实施授权,明明已经加入了策略中指定的Azure AD组,但一直收到“Access denied”提示。
相关代码
Startup.cs
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // Get the scopes from the configuration (appsettings.json) var initialScopes = Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' '); // Add sign-in with Microsoft services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) // Add the possibility of acquiring a token to call a protected web API .EnableTokenAcquisitionToCallDownstreamApi(initialScopes) // Enables controllers and pages to get GraphServiceClient by dependency injection // And use an in memory token cache .AddMicrosoftGraph(Configuration.GetSection("DownstreamApi")) .AddDistributedTokenCaches(); services.AddAuthorization(options => { options.AddPolicy("it", policy => policy.RequireClaim("groups", "Azure group ID here")); }); // Register AadService and PbiEmbedService for dependency injection services.AddScoped(typeof(AadService)) .AddScoped(typeof(PbiEmbedService)) .AddScoped(typeof(PowerBiServiceApi)); services.AddControllersWithViews(options => { var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); options.Filters.Add(new AuthorizeFilter(policy)); }); // Enables a UI and controller for sign in and sign out. services.AddRazorPages() .AddMicrosoftIdentityUI(); // Session/cookie variables etc services.AddDistributedMemoryCache(); services.AddSession(); // Loading appsettings.json in C# Model classes services.Configure<AzureAd>(Configuration.GetSection("AzureAd")) .Configure<PowerBI>(Configuration.GetSection("PowerBI")); // Add the UI support to handle claims challenges services.AddServerSideBlazor() .AddMicrosoftIdentityConsentHandler(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseSession(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapRazorPages(); }); } }
控制器授权代码
[AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")] [Authorize(Policy = "it")] public Task<IActionResult> Index()
排查与解决方法
- 确认组声明是否存在于令牌中:Azure AD默认不会在ID令牌中返回所有组,当用户组数量超过限制时,只会返回
hasgroups声明。需要在Azure AD应用注册的「令牌配置」中启用组声明,选择「安全组」并设置为「组ID」格式。 - 检查组ID是否正确:确保策略中填写的是Azure AD组的对象ID(不是显示名称),可在Azure AD组详情页复制正确的对象ID替换代码中的占位符。
- 清除令牌缓存:用户登录后组变更不会同步到现有令牌,需让用户注销后重新登录,或清除应用会话缓存。
- 验证声明名称:部分场景下组声明的完整名称是
http://schemas.microsoft.com/ws/2008/06/identity/claims/groups,而非groups。可通过调试查看用户Claims集合确认,若为完整URI则修改策略:services.AddAuthorization(options => { options.AddPolicy("it", policy => policy.RequireClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/groups", "Azure group ID here")); }); - 调试用户声明:在控制器中添加代码查看当前用户的所有声明,确认组ID是否存在:
public Task<IActionResult> Index() { var userClaims = User.Claims.Select(c => $"{c.Type}: {c.Value}").ToList(); // 可将userClaims输出到日志或调试窗口 return ...; }
内容的提问来源于stack exchange,提问作者crissb3
相关产品推荐
相关产品推荐

