【问题标题】:How to use Microsoft Graph API to get all the groups for Authorization in .net core application?如何使用 Microsoft Graph API 获取 .net 核心应用程序中的所有授权组?
【发布时间】:2019-09-26 15:09:52
【问题描述】:

我正在开发 .net 核心项目。我正在尝试使用 AD 组实现授权。我的要求是,我在 azure 广告中有很多组。如果当前用户属于 azure ad 中的任何可用组,那么我想授权这些用户访问用 .net 核心应用程序编写的 api。我尝试如下。我在下面添加了两个类

 public class IsMemberOfGroupHandler : AuthorizationHandler<IsMemberOfGroupRequirement>
    {
        protected override Task HandleRequirementAsync(
            AuthorizationHandlerContext context, IsMemberOfGroupRequirement requirement)
        {
            var groupClaim = context.User.Claims
                 .FirstOrDefault(claim => claim.Type == "groups" &&
                     claim.Value.Equals(requirement.GroupId, StringComparison.InvariantCultureIgnoreCase));

            if (groupClaim != null)
                context.Succeed(requirement);

            return Task.CompletedTask;
        }
    }

 public class IsMemberOfGroupRequirement : IAuthorizationRequirement
    {
        public readonly string GroupId;
        public readonly string GroupName;

        public IsMemberOfGroupRequirement(string groupName, string groupId)
        {
            GroupName = groupName;
            GroupId = groupId;
        }
    }

下面是我的启动课。

 services.AddAuthorization(options =>
            {
                var adGroupConfig = new List<AdGroupConfig>();
                _configuration.Bind("AdGroups", adGroupConfig);

                foreach (var adGroup in adGroupConfig)
                    options.AddPolicy(
                        adGroup.GroupName,
                        policy =>
                            policy.AddRequirements(new IsMemberOfGroupRequirement(adGroup.GroupName, adGroup.GroupId)));
            });

以上代码检查配置文件中可用的组。现在我的要求是使用 microsoft graph api 来获取所有可用的组。我找不到任何方法来处理这个要求。有人可以帮我弄这个吗?任何帮助,将不胜感激。谢谢

【问题讨论】:

    标签: asp.net-core .net-core azure-active-directory authorization microsoft-graph-api


    【解决方案1】:

    请先检查this code sample,它使用 OpenID Connect 登录用户并使用 MSAL 获取 Microsoft Graph API 令牌以退出组。

    如果通过编辑清单将您的应用程序配置为接收组声明:

    {
      ...
      "errorUrl": null,
      "groupMembershipClaims": "SecurityGroup",
      ...
    }
    

    登录用户所属的安全组的对象 ID 在令牌的组声明中返回。

    如果用户是超过超额限制的组的成员(SAML 令牌为 150 个,JWT 令牌为 200 个),则 Microsoft 标识平台不会在令牌中发出组声明。相反,它在令牌中包含一个超额声明,指示应用程序查询 Graph API 以检索用户的组成员资格。

    {
      ...
      "_claim_names": {
        "groups": "src1"
        },
        {
       "_claim_sources": {
        "src1": {
            "endpoint":"[Graph Url to get this user's group membership from]"
            }
        }
      ...
    }
    

    所以你可以按照流程进行:

    1. 检查声明_claim_names,其中一个值为组。这表示超龄。

    2. 如果找到,请调用 _claim_sources 中指定的端点以获取用户组。

    3. 如果没有找到,请查看用户组的组声明。

    当然,您可以直接调用 Microsoft Graph API 来退出当前用户的群组无需使用group claims

    https://docs.microsoft.com/en-us/graph/api/user-list-memberof?view=graph-rest-1.0&tabs=http

    然后您可以根据该组进行授权。例如,如果使用策略:

    services.AddAuthorization(options =>
    {
        options.AddPolicy("GroupsCheck", policy =>
            policy.Requirements.Add(new GroupsCheckRequirement("YourGroupID")));
    });
    services.AddScoped<IAuthorizationHandler, GroupsCheckHandler>();
    

    GroupsCheckRequirement.cs:

    public class GroupsCheckRequirement : IAuthorizationRequirement
    {
        public string groups;
    
        public GroupsCheckRequirement(string groups)
        {
            this.groups = groups;
        }
    }
    

    GroupsCheckHandler.cs:

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

    然后使用策略:

    [Authorize(Policy = "GroupsCheck")] 
    

    【讨论】:

    • 嘿,谢谢。很有用。一件事我不是很清楚。 "_claim_names": { "groups": "src1" },我可以知道这是什么以及我必须在哪里添加它吗?
    • 这是从 Azure AD 返回的令牌中的声明如果您使用组声明但组帐户超额限制。如果使用graph api,则无需担心。
    • 谢谢。只是想知道有没有办法在 jwt 令牌中获取组名?
    • 如果要包含 jwt 令牌,只需使用组声明。但它对大量组有限制。
    • 我的组数有限。我尝试添加“groupMembershipClaims”:“SecurityGroup”,。这会返回我的组 ID,但我想获取组名。有什么办法吗?
    【解决方案2】:

    您可以使用this graph api 获取该用户直接所属的所有组。

    GET /me/memberOf
    

    在.net-core 中你可以使用GraphServiceClient 来调用graph api。这是一个示例供您参考。

    var graphClient = new GraphServiceClient(
                    new DelegateAuthenticationProvider(
                        (requestMessage) =>
                        {
                            // Get back the access token.
                            var accessToken = "";
    
                            if (!String.IsNullOrEmpty(accessToken))
                            {
                                // Configure the HTTP bearer Authorization Header
                                requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
                            }
                            else
                            {
                                throw new Exception("Invalid authorization context");
                            }
    
                            return (Task.FromResult(0));
                        }
                        ));
                var groups = graphClient.Me.MemberOf.Request().GetAsync().Result;
    

    【讨论】:

    • 感谢您的回答 Tony Ju。我可以知道我必须在哪里添加上面的代码。我想实现基于组的授权。
    • @Niranjan 看看这篇关于授权的文章。 azure.microsoft.com/en-us/resources/samples/…
    • @Niranjan 上面的代码是使用 Graph api 获取用户可用的组。
    猜你喜欢
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多