.net core应用程序中如何进行基于组的授权?

Nir*_*jan 5 c# authorization azure-active-directory asp.net-core

净核心应用程序。我的要求是添加基于组的授权。我是 Azure AD 的用户。我属于一些名称以 BR 和 AR 开头的组。属于 AR 组的用户只能访问我的 API。目前我的客户端应用程序是 Swagger,我仅通过 swagger 访问 APIS。

例如,在启动时我可以使用以下代码。

services.AddAuthorization(options => {
                options.AddPolicy("AR-BitBucket-User",
                        policyBuilder => policyBuilder.RequireClaim("groups",
                        "6be4f534-dcf5-489e-b57d-c7bb46be8d6b"));
            });  
Run Code Online (Sandbox Code Playgroud)

在控制器中,

[Authorize("AR-BitBucket-User")]
Run Code Online (Sandbox Code Playgroud)

在上面的方法中,我进行了硬编码,但我不想硬编码。首先,我没有在 JWT 令牌中获取组信息,但我得到了

hasGroups:true 在我的 JWT 令牌中。我想从 Graph API 获取它,而不是硬编码。有人可以帮我怎么做吗?我无法在互联网上获得任何相关示例。那么有人可以帮助我吗?

Jim*_* Xu 6

如果要将应用程序配置为接收组声明,则需要按照 Manifest 文件中的方式设置“ groupMembershipClaims ”值。SecurityGroup

\n\n
    \n
  1. 在应用程序注册门户的应用程序设置页面中,单击“清单”以打开内联清单编辑器。

  2. \n
  3. 通过找到“groupMembershipClaims”设置并将其值设置为“SecurityGroup”来编辑清单。

  4. \n
  5. 保存清单。

  6. \n
\n\n
    {\n      ...\n      "errorUrl": null,\n      "groupMembershipClaims": "SecurityGroup",\n      ...\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

当为应用程序启用组声明时,Azure AD 在 JWT 和 SAML 令牌中包含一个声明,其中包含用户所属的所有组的对象标识符 (objectId),包括可传递的组成员身份。

\n\n
\n

但请注意,为了确保令牌大小不超过 HTTP 标头大小限制,Azure AD 限制其包含在组声明中的 objectId 数量。如果用户属于的组数超过了超额限制(SAML 令牌为 150 个,JWT 令牌为 200 个),则 Azure AD 不会在令牌中发出组声明。相反,它在令牌中包含超额声明,指示应用程序查询图形 API 以检索用户的组成员身份。欲了解更多详情,请参阅博客

\n
\n\n

在此输入图像描述

\n\n

所以你需要做一些过程:

\n\n
\n
    \n
  1. 检查声明 _claim_names 的值之一是否为组。这表明超额。

  2. \n
  3. 如果找到,则调用 _claim_sources 中指定的端点以获取 user\xe2\x80\x99s 组。

  4. \n
  5. 如果没有找到,请查看 user\xe2\x80\x99s 组的组声明。

  6. \n
\n
\n\n

当然,您可以直接调用Microsoft Graph API来停用当前用户组,而无需使用group claims

\n\n

关于如何基于该组进行授权,您可以创建一个策略。更多详细信息,请参阅文档。例如

\n\n

启动.cs

\n\n
    services.AddAuthorization(options =>\n    {\n        options.AddPolicy("CheckGroups", policy =>\n            policy.Requirements.Add(new GroupsCheckRequirement("YourGroupID")));\n    });\n    services.AddScoped<IAuthorizationHandler, GroupsCheckHandler>();\n
Run Code Online (Sandbox Code Playgroud)\n\n

GroupsCheckRequirement.cs:

\n\n
    public class GroupsCheckRequirement : IAuthorizationRequirement\n    {\n        public string groups;\n\n        public GroupsCheckRequirement(string groups)\n        {\n            this.groups = groups;\n        }\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

GroupsCheckHandler.cs:

\n\n
    public class GroupsCheckHandler : AuthorizationHandler<GroupsCheckRequirement>\n    {\n        private readonly ITokenAcquisition tokenAcquisition;\n        private readonly IMSGraphService graphService;\n\n        public GroupsCheckHandler(ITokenAcquisition tokenAcquisition, IMSGraphService MSGraphService)\n        {\n            this.tokenAcquisition = tokenAcquisition;\n            this.graphService = MSGraphService;\n        }\n        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,\n                                                  GroupsCheckRequirement requirement)\n        {\n            string accessToken = await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new[] { Constants.ScopeUserRead, Constants.ScopeDirectoryReadAll });\n\n            User me = await graphService.GetMeAsync(accessToken);\n\n            IList<Group> groups = await graphService.GetMyMemberOfGroupsAsync(accessToken);\n\n            var result = false;\n            foreach (var group in groups)\n            {\n                if (requirement.groups.Equals(group.Id))\n                {\n                    result = true;\n                }\n            }\n\n            if (result)\n            {\n                context.Succeed(requirement);\n            }\n\n        }\n\n\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后使用策略:

\n\n
[Authorize(Policy = "CheckGroups")] \n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

此外,您还可以通过 ASP.NET Core 中间件库来实现它。RoleClaimTypeasp.net 中间件通过在的 属性中指定声明来支持从声明填充的角色TokenValidationParameters。由于groups声明包含安全组的对象 ID,而不是实际名称,因此您可以使用组 ID,而不是组名称。欲了解更多详情,请参阅示例

\n\n

启动.cs

\n\n
// The following lines code instruct the asp.net core middleware to use the data in the "groups" claim in the Authorize attribute and User.IsInrole()\n            // See https://learn.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.2 for more info.\n            services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>\n            {\n                // Use the groups claim for populating roles\n                options.TokenValidationParameters.RoleClaimType = "groups";\n            });\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后使用它

\n\n
[Authorize(Roles = \xe2\x80\x9cGroup-object-id")] // In controllers\n// or\nUser.IsInRole("Group-object-id"); // In methods\n
Run Code Online (Sandbox Code Playgroud)\n