C# Dotnet Core 2.2-Azure AD Auth工作,但角色库返回拒绝访问

C# Dotnet Core 2.2-Azure AD Auth工作,但角色库返回拒绝访问,c#,azure,asp.net-core,.net-core,azure-active-directory,C#,Azure,Asp.net Core,.net Core,Azure Active Directory,我试图让角色在.NETCore2.2中工作,但其他解决方案都不起作用 在Startup.cs中,Microsoft在一个新的.Net 2.2中生成了这段代码,由于某种原因,它不起作用,但是让这个块起作用并不是主题,尽管很高兴知道为什么它不起作用。表示未指定authenticationScheme,并且未找到DefaultChallengeScheme。但这是微软创造的 services.AddAuthentication(AzureADDefaults.AuthenticationScheme)

我试图让角色在.NETCore2.2中工作,但其他解决方案都不起作用

在Startup.cs中,Microsoft在一个新的.Net 2.2中生成了这段代码,由于某种原因,它不起作用,但是让这个块起作用并不是主题,尽管很高兴知道为什么它不起作用。表示未指定authenticationScheme,并且未找到DefaultChallengeScheme。但这是微软创造的

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
                .AddAzureAd(options => Configuration.Bind("AzureAd", options));
在我真正的Startup.cs中,我不得不使用下面的内容

services.AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddAzureAd(options => Configuration.Bind("AzureAd", options))
            .AddCookie();
因此,以上是我让Azure AD使用[Authorize]属性的唯一方法。问题是,当我尝试使用角色进行授权时。我试过许多建议,但都没有成功。只要我有一个[AuthorizeRoles=],我就会被重定向到Microsoft为Azure AD生成的AccountController中的AccessDenied方法,基本上拒绝访问。我正在使用我在广告中创建的角色,也在Azure广告中创建了一个组,还使用了一个名为Domain Users的角色,该角色基本上授予公司中的每个员工,是每个员工拥有的最基本的授权。如果域用户被拒绝访问,那么我不知道我在这里不理解什么


我已经关注了Microsoft文档中的角色,但是没有任何内容表明我需要添加更多的服务。添加身份验证选项。

您需要在AzureAD中配置应用程序清单以接收AD角色

将清单中的groupMembershipClaims值更改为All


请注意,如果您有大量的组,则最终可能会导致响应过大,因此可能需要将所有组缩减为您实际想要流动的组。

您需要在AzureAD中配置应用程序清单以接收AD角色

将清单中的groupMembershipClaims值更改为All


请注意,如果您有大量的组,则最终可能会导致响应过大,因此可能需要将所有组精简为您实际想要流动的组。

请首先确认您在令牌中获得了组,在将清单中的groupMembershipClaims值更改为all后,您可以在控制器中输入以下代码:

 var claims = User.Claims;
[Authorize(Policy = "CanAccessGroup")]
public IActionResult About()
{
    return View();
}
在应用程序中对用户进行身份验证后,您应该获得以下组声明:

然后可以将属性与命名策略一起使用,然后在启动时定义策略以要求组声明并设置允许的组ID:

services.AddAuthorization(options =>
{
    options.AddPolicy(
        "CanAccessGroup",
        policyBuilder => policyBuilder.RequireClaim("groups", "0c71eab2-6618-4c53-bcce-806xxxxxx"));
});
在控制器中:

 var claims = User.Claims;
[Authorize(Policy = "CanAccessGroup")]
public IActionResult About()
{
    return View();
}
如果组id不在用户组声明中,访问将被拒绝

表示未指定authenticationScheme,并且未找到DefaultChallengeScheme。但这是微软创造的

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
                .AddAzureAd(options => Configuration.Bind("AzureAd", options));
如果在VS2017中使用默认的工作或学校帐户模板,安装的Microsoft.AspNetCore.Authentication.AzureAD.UI软件包版本将为v2.2.0,并且生成的代码为:

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
    .AddAzureAD(options => Configuration.Bind("AzureAd", options));

请首先确认您获得了令牌中的组,将清单中的groupMembershipClaims值更改为All后,您可以在控制器中输入以下代码:

 var claims = User.Claims;
[Authorize(Policy = "CanAccessGroup")]
public IActionResult About()
{
    return View();
}
在应用程序中对用户进行身份验证后,您应该获得以下组声明:

然后可以将属性与命名策略一起使用,然后在启动时定义策略以要求组声明并设置允许的组ID:

services.AddAuthorization(options =>
{
    options.AddPolicy(
        "CanAccessGroup",
        policyBuilder => policyBuilder.RequireClaim("groups", "0c71eab2-6618-4c53-bcce-806xxxxxx"));
});
在控制器中:

 var claims = User.Claims;
[Authorize(Policy = "CanAccessGroup")]
public IActionResult About()
{
    return View();
}
如果组id不在用户组声明中,访问将被拒绝

表示未指定authenticationScheme,并且未找到DefaultChallengeScheme。但这是微软创造的

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
                .AddAzureAd(options => Configuration.Bind("AzureAd", options));
如果在VS2017中使用默认的工作或学校帐户模板,安装的Microsoft.AspNetCore.Authentication.AzureAD.UI软件包版本将为v2.2.0,并且生成的代码为:

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
    .AddAzureAD(options => Configuration.Bind("AzureAd", options));

以下是对我有效的方法,.Net Core 2.2 Web应用程序使用角色

编辑应用程序清单以包括角色,例如

"appRoles": [
        {
            "allowedMemberTypes": [
                "User"
            ],
            "description": "Admins have the power.",
            "displayName": "Admin",
            "id": "282fc418-cf3a-4a3a-89f8-6500c64695ff",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "value": "Admin"
        },
        {
            "allowedMemberTypes": [
                "User"
            ],
            "description": "Writers have the ability to edit app data.",
            "displayName": "Writer",
            "id": "3aa1a322-2918-4005-8cc3-51cba010ccc0",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "value": "Writer"
        },
        {
            "allowedMemberTypes": [
                "User"
            ],
            "description": "Readers have the ability to read app data.",
            "displayName": "Reader",
            "id": "239f93af-4cc0-4d0e-ad04-bda1f8ac2a91",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "value": "Reader"
        }
    ]
Startup.cs

services.AddAuthentication(sharedOptions =>
    {
        sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddAzureAd(options => Configuration.Bind("AzureAd", options))
    .AddCookie();

services.AddHttpContextAccessor();
在顶部代码块中添加扩展以解决您提到的问题

AzureAdAuthenticationBuilderExtensions.cs

public static class AzureAdAuthenticationBuilderExtensions
{
    public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder)
        => builder.AddAzureAd(_ => { });

    public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action<AzureAdOptions> configureOptions)
    {
        builder.Services.Configure(configureOptions);
        builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, ConfigureAzureOptions>();
        builder.AddOpenIdConnect();
        return builder;
    }

    private class ConfigureAzureOptions : IConfigureNamedOptions<OpenIdConnectOptions>
    {
        private readonly AzureAdOptions _azureOptions;

        public ConfigureAzureOptions(IOptions<AzureAdOptions> azureOptions)
        {
            _azureOptions = azureOptions.Value;
        }

        public void Configure(string name, OpenIdConnectOptions options)
        {
            options.ResponseType = "token id_token";
            options.Resource = _azureOptions.TargetApiAppId;
            options.SaveTokens = true;
            options.ClientId = _azureOptions.ClientId;
            options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}";
            options.UseTokenLifetime = true;
            options.CallbackPath = _azureOptions.CallbackPath;
            options.RequireHttpsMetadata = false;
        }

        public void Configure(OpenIdConnectOptions options)
        {
            Configure(Options.DefaultName, options);
        }
    }
}
在企业应用程序刀片中为用户分配角色:

装饰您的控制器:

[Authorize(Roles = "Writer")]
AccountController.cs

public class AccountController : Controller
{
    [HttpGet]
    public IActionResult SignIn()
    {
        var redirectUrl = Url.Action(nameof(HomeController.Index), "Home");
        return Challenge(
            new AuthenticationProperties { RedirectUri = redirectUrl },
            OpenIdConnectDefaults.AuthenticationScheme);
    }

    [HttpGet]
    public IActionResult SignOut()
    {
        var callbackUrl = Url.Action(nameof(SignedOut), "Account", values: null, protocol: Request.Scheme);
        return SignOut(
            new AuthenticationProperties { RedirectUri = callbackUrl },
            CookieAuthenticationDefaults.AuthenticationScheme,
            OpenIdConnectDefaults.AuthenticationScheme);
    }

    [HttpGet]
    public IActionResult SignedOut()
    {
        if (User.Identity.IsAuthenticated)
        {
            // Redirect to home page if the user is authenticated.
            return RedirectToAction(nameof(HomeController.Index), "Home");
        }

        return View();
    }

    [HttpGet]
    public IActionResult AccessDenied()
    {
        return View();
    }
}

以下是对我有效的方法,.Net Core 2.2 Web应用程序使用角色

编辑应用程序清单以包括角色,例如

"appRoles": [
        {
            "allowedMemberTypes": [
                "User"
            ],
            "description": "Admins have the power.",
            "displayName": "Admin",
            "id": "282fc418-cf3a-4a3a-89f8-6500c64695ff",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "value": "Admin"
        },
        {
            "allowedMemberTypes": [
                "User"
            ],
            "description": "Writers have the ability to edit app data.",
            "displayName": "Writer",
            "id": "3aa1a322-2918-4005-8cc3-51cba010ccc0",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "value": "Writer"
        },
        {
            "allowedMemberTypes": [
                "User"
            ],
            "description": "Readers have the ability to read app data.",
            "displayName": "Reader",
            "id": "239f93af-4cc0-4d0e-ad04-bda1f8ac2a91",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "value": "Reader"
        }
    ]
Startup.cs

services.AddAuthentication(sharedOptions =>
    {
        sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddAzureAd(options => Configuration.Bind("AzureAd", options))
    .AddCookie();

services.AddHttpContextAccessor();
在顶部代码块中添加扩展以解决您提到的问题

AzureAdAuthenticationBuilderExtensions.cs

public static class AzureAdAuthenticationBuilderExtensions
{
    public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder)
        => builder.AddAzureAd(_ => { });

    public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action<AzureAdOptions> configureOptions)
    {
        builder.Services.Configure(configureOptions);
        builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, ConfigureAzureOptions>();
        builder.AddOpenIdConnect();
        return builder;
    }

    private class ConfigureAzureOptions : IConfigureNamedOptions<OpenIdConnectOptions>
    {
        private readonly AzureAdOptions _azureOptions;

        public ConfigureAzureOptions(IOptions<AzureAdOptions> azureOptions)
        {
            _azureOptions = azureOptions.Value;
        }

        public void Configure(string name, OpenIdConnectOptions options)
        {
            options.ResponseType = "token id_token";
            options.Resource = _azureOptions.TargetApiAppId;
            options.SaveTokens = true;
            options.ClientId = _azureOptions.ClientId;
            options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}";
            options.UseTokenLifetime = true;
            options.CallbackPath = _azureOptions.CallbackPath;
            options.RequireHttpsMetadata = false;
        }

        public void Configure(OpenIdConnectOptions options)
        {
            Configure(Options.DefaultName, options);
        }
    }
}
在企业应用程序刀片中为用户分配角色:

装饰您的控制器:

[Authorize(Roles = "Writer")]
AccountController.cs

public class AccountController : Controller
{
    [HttpGet]
    public IActionResult SignIn()
    {
        var redirectUrl = Url.Action(nameof(HomeController.Index), "Home");
        return Challenge(
            new AuthenticationProperties { RedirectUri = redirectUrl },
            OpenIdConnectDefaults.AuthenticationScheme);
    }

    [HttpGet]
    public IActionResult SignOut()
    {
        var callbackUrl = Url.Action(nameof(SignedOut), "Account", values: null, protocol: Request.Scheme);
        return SignOut(
            new AuthenticationProperties { RedirectUri = callbackUrl },
            CookieAuthenticationDefaults.AuthenticationScheme,
            OpenIdConnectDefaults.AuthenticationScheme);
    }

    [HttpGet]
    public IActionResult SignedOut()
    {
        if (User.Identity.IsAuthenticated)
        {
            // Redirect to home page if the user is authenticated.
            return RedirectToAction(nameof(HomeController.Index), "Home");
        }

        return View();
    }

    [HttpGet]
    public IActionResult AccessDenied()
    {
        return View();
    }
}

我把它改成了all,但我没有得到任何不同的回报。没有角色或组。您将如何精简到所需的值?我无法指定我想要的角色类型,表示无效值。但我仍然没有得到任何一个。在这一点上,我只能指向AzureAD文档,这是针对.Net核心的吗?是的,不幸的是,这是针对.Net的

,我们正在寻找与.Net Core不同的解决方案。组的流动仍应使用标志,这不是特定于.Net版本的。添加断点并查看用户是否包含角色声明。如果没有,可能是AAD配置问题。我将它改为all,但我没有得到任何不同的回复。没有角色或组。您将如何精简到所需的值?我无法指定我想要的角色类型,表示无效值。但我仍然没有得到它们。在这一点上,我只能指向AzureAD文档,这是针对.Net Core的吗?是的,不幸的是,这是针对.Net的,我们正在寻找不同于.Net Core的解决方案。组的流动仍然应该与标志一起发生,这不是针对.Net版本的。添加断点并查看用户是否包含角色声明。如果没有,可能是AAD配置问题。我想这是我迄今为止看到的最好的方法。我希望[authorized roles=]属性能够正常工作,我们能不能在团队中做到这一点?当我使用他们在模板中生成的services.AddAuthentication代码时,这就是我得到的。这是可行的,但问题是我得到了100个组。唯一的选择是使用安全组的值,这使我仍然处于100秒。我想没有别的办法可以把它删减了。但是请求/响应太大,显示错误的请求。@DanielJackson,那么您不应该使用组,使用角色,您可以在应用程序清单中定义应用程序中的角色,然后为其分配用户。一旦你做了这两件事,你得到的JWT中就会有一个名为roles的声明,其中包含用户的角色。是的,你是对的,它花了一些时间过滤掉了影响,但我现在在代码中得到了应用程序角色,并且[AuthorizeRoles=role]正在工作!谢谢你的帮助。我想这是迄今为止我见过的最好的方法。我希望[authorized roles=]属性能够正常工作,我们能不能在团队中做到这一点?当我使用他们在模板中生成的services.AddAuthentication代码时,这就是我得到的。这是可行的,但问题是我得到了100个组。唯一的选择是使用安全组的值,这使我仍然处于100秒。我想没有别的办法可以把它删减了。但是请求/响应太大,显示错误的请求。@DanielJackson,那么您不应该使用组,使用角色,您可以在应用程序清单中定义应用程序中的角色,然后为其分配用户。一旦你做了这两件事,你得到的JWT中就会有一个名为roles的声明,其中包含用户的角色。是的,你是对的,它花了一些时间过滤掉了影响,但我现在在代码中得到了应用程序角色,并且[AuthorizeRoles=role]正在工作!谢谢你的帮助。这也是我发现的。必须使用应用程序清单中定义的应用程序角色。不过最酷的是,可以在我们的常规本地广告中创建一个角色,该广告将显示在Azure广告中。该角色可以通过在应用程序清单中创建的一个角色分配给应用程序。然后,每次你向本地广告添加用户时,一旦同步到Azure广告,它就会自动获得访问权限。真酷!我在另一个Web应用程序中这样做,将它与基于策略的身份验证结合起来,它变得非常强大。例如,services.AddAuthorizationoptions=>{options.AddPolicyAnalyst,policy=>policy.requireRoledDataAnalyst;options.AddPolicyReader,policy=>policy.RequireAssertioncontext=>context.User.HasClaimClaimTypes.Role,DataAnalyst | | context.User.HasClaimClaimTypes.Role,DataReader;};我也发现了这一点。必须使用应用程序清单中定义的应用程序角色。但最酷的是,可以在我们的常规本地广告中创建角色,该广告将显示在Azure广告中。该角色可以通过在应用程序清单中创建的角色之一分配给应用程序。然后,每次将用户添加到premise AD,一旦同步到Azure AD,它将自动获得访问权限。真的很酷!我正在另一个Web应用中这样做,将它与基于策略的身份验证结合起来,它将变得非常强大。例如,services.AddAuthorizationoptions=>{options.AddPolicyAnalyst,policy=>policy.RequireRoleDataAnalyst;options.AddPolicyReader,policy=>policy.RequireAssertioncontext=>context.User.HasClaimClaimTypes.Role,DataAnalyst | | context.User.HasClaimClaimTypes.Role,DataReader;};