在 Azure Active Directory 中使用授权属性
Using the Authorize attribute with Azure Active Directory
我正在尝试在测试应用程序上使用 [Authorize(Roles="test")] and/or call User.IsInRole("test") 但它不适用于我。在 Azure 管理门户的应用程序配置中,我在应用程序清单中启用了 SecurityGroup 声明,还设置了委派权限以允许 "Read all groups" 和 "Read directory data"。执行此操作后,我能够在 (ClaimsPrincipal.Current.Identity as ClaimsIdentity).FindAll("groups") 中看到测试组的 SID,但授权属性和对 IsInRole 的调用不起作用。是否需要其他任何东西才能让它发挥作用?
Azure AD 不发送角色声明中的组,也不发送组的名称(在多租户系统中,这意义不大:"admin" 在 contoso 中可能具有完全不同的语义来自 fabrikam 中的 "admin")。 Azure AD 有一个代表实际角色的新构造,而不是组。如果您想根据 角色 的名称检查访问权限,请参阅 https://github.com/Azure-Samples/active-directory-dotnet-webapp-roleclaims/blob/master/WebApp-RoleClaims-DotNet 以获取使用应用程序角色的示例。
如果您想改为检查组的授权,则需要将组声明类型分配为 RoleClaimType(在 https://github.com/Azure-Samples/active-directory-dotnet-webapp-roleclaims/blob/master/WebApp-RoleClaims-DotNet/App_Start/Startup.Auth.cs 中,您可以看到它是如何为应用程序角色完成的)以便 ASP.NET 知道这是声明验证 Authorize 和 IsInRole 何时发挥作用。此外,假设您没有获得组名,则需要对组的 objectId 执行检查。如果你想使用组并检查组名,它会变得复杂。您需要调用图 API 将组的 ObjectId 转换为其名称,并相应地增加传入的声明集合。
在 ASP.NET 5 和 MVC 6 中,您需要做的就是正确配置。这是对我来说很有魅力的代码:
public void ConfigureApplication(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseIISPlatformHandler();
app.UseStaticFiles();
app.UseCookieAuthentication(options =>
{
options.AutomaticAuthenticate = true;
});
app.UseOpenIdConnectAuthentication(options =>
{
options.AutomaticChallenge = true;
options.ClientId = Configuration.Get<string>("Authentication:AzureAd:ClientId");
options.Authority = Configuration.Get<string>("Authentication:AzureAd:AADInstance") + "Common";
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
RoleClaimType = "roles"
};
options.Events = new OpenIdConnectEvents
{
OnAuthenticationValidated = (context) => Task.FromResult(0),
OnAuthenticationFailed = (context) =>
{
context.Response.Redirect("/Home/Error");
context.HandleResponse(); // Suppress the exception
return Task.FromResult(0);
},
OnRemoteError = (context) => Task.FromResult(0)
};
});
app.UseMvc(routes =>
{
routes.MapRoute(name: "default", template: "{controller=Dashboard}/{action=Index}/{id?}");
});
DatabaseInitializer.InitializaDatabaseAsync(app.ApplicationServices).Wait();
}
我正在尝试在测试应用程序上使用 [Authorize(Roles="test")] and/or call User.IsInRole("test") 但它不适用于我。在 Azure 管理门户的应用程序配置中,我在应用程序清单中启用了 SecurityGroup 声明,还设置了委派权限以允许 "Read all groups" 和 "Read directory data"。执行此操作后,我能够在 (ClaimsPrincipal.Current.Identity as ClaimsIdentity).FindAll("groups") 中看到测试组的 SID,但授权属性和对 IsInRole 的调用不起作用。是否需要其他任何东西才能让它发挥作用?
Azure AD 不发送角色声明中的组,也不发送组的名称(在多租户系统中,这意义不大:"admin" 在 contoso 中可能具有完全不同的语义来自 fabrikam 中的 "admin")。 Azure AD 有一个代表实际角色的新构造,而不是组。如果您想根据 角色 的名称检查访问权限,请参阅 https://github.com/Azure-Samples/active-directory-dotnet-webapp-roleclaims/blob/master/WebApp-RoleClaims-DotNet 以获取使用应用程序角色的示例。 如果您想改为检查组的授权,则需要将组声明类型分配为 RoleClaimType(在 https://github.com/Azure-Samples/active-directory-dotnet-webapp-roleclaims/blob/master/WebApp-RoleClaims-DotNet/App_Start/Startup.Auth.cs 中,您可以看到它是如何为应用程序角色完成的)以便 ASP.NET 知道这是声明验证 Authorize 和 IsInRole 何时发挥作用。此外,假设您没有获得组名,则需要对组的 objectId 执行检查。如果你想使用组并检查组名,它会变得复杂。您需要调用图 API 将组的 ObjectId 转换为其名称,并相应地增加传入的声明集合。
在 ASP.NET 5 和 MVC 6 中,您需要做的就是正确配置。这是对我来说很有魅力的代码:
public void ConfigureApplication(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseIISPlatformHandler();
app.UseStaticFiles();
app.UseCookieAuthentication(options =>
{
options.AutomaticAuthenticate = true;
});
app.UseOpenIdConnectAuthentication(options =>
{
options.AutomaticChallenge = true;
options.ClientId = Configuration.Get<string>("Authentication:AzureAd:ClientId");
options.Authority = Configuration.Get<string>("Authentication:AzureAd:AADInstance") + "Common";
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
RoleClaimType = "roles"
};
options.Events = new OpenIdConnectEvents
{
OnAuthenticationValidated = (context) => Task.FromResult(0),
OnAuthenticationFailed = (context) =>
{
context.Response.Redirect("/Home/Error");
context.HandleResponse(); // Suppress the exception
return Task.FromResult(0);
},
OnRemoteError = (context) => Task.FromResult(0)
};
});
app.UseMvc(routes =>
{
routes.MapRoute(name: "default", template: "{controller=Dashboard}/{action=Index}/{id?}");
});
DatabaseInitializer.InitializaDatabaseAsync(app.ApplicationServices).Wait();
}